COMPUTER VISION CAPSTONE PROJECT AIML PNEUMONIA DETECTION CHALLENGE
CV 1 Batch
#mendatory pips to install
%pip install pydicom
%pip install opencv-python
%pip install scikit-image
Requirement already satisfied: pydicom in c:\anacondapython\envs\tensorflow\lib\site-packages (2.4.4) Note: you may need to restart the kernel to use updated packages. Requirement already satisfied: opencv-python in c:\anacondapython\envs\tensorflow\lib\site-packages (4.9.0.80) Requirement already satisfied: numpy>=1.17.3 in c:\anacondapython\envs\tensorflow\lib\site-packages (from opencv-python) (1.22.3) Note: you may need to restart the kernel to use updated packages. Requirement already satisfied: scikit-image in c:\anacondapython\envs\tensorflow\lib\site-packages (0.22.0) Requirement already satisfied: imageio>=2.27 in c:\anacondapython\envs\tensorflow\lib\site-packages (from scikit-image) (2.34.0) Requirement already satisfied: packaging>=21 in c:\anacondapython\envs\tensorflow\lib\site-packages (from scikit-image) (21.3) Requirement already satisfied: lazy_loader>=0.3 in c:\anacondapython\envs\tensorflow\lib\site-packages (from scikit-image) (0.3) Requirement already satisfied: scipy>=1.8 in c:\anacondapython\envs\tensorflow\lib\site-packages (from scikit-image) (1.8.0) Requirement already satisfied: tifffile>=2022.8.12 in c:\anacondapython\envs\tensorflow\lib\site-packages (from scikit-image) (2024.2.12) Requirement already satisfied: numpy>=1.22 in c:\anacondapython\envs\tensorflow\lib\site-packages (from scikit-image) (1.22.3) Requirement already satisfied: pillow>=9.0.1 in c:\anacondapython\envs\tensorflow\lib\site-packages (from scikit-image) (9.0.1) Requirement already satisfied: networkx>=2.8 in c:\anacondapython\envs\tensorflow\lib\site-packages (from scikit-image) (3.2.1) Requirement already satisfied: pyparsing!=3.0.5,>=2.0.2 in c:\anacondapython\envs\tensorflow\lib\site-packages (from packaging>=21->scikit-image) (3.0.4) Note: you may need to restart the kernel to use updated packages.
#import library core
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import os
import seaborn as sns
#read dcm's
import pydicom as pdcm
#import zip
import zipfile as zp
#import cv2 open cv
import cv2
#import image checker
from PIL import Image
from skimage import measure, morphology
from skimage.feature import graycomatrix, graycoprops
#import math
import math
#lets begin with train csv convert to dataframe
train_df = pd.read_csv('stage_2_train_labels.csv')
train_df
| patientId | x | y | width | height | Target | |
|---|---|---|---|---|---|---|
| 0 | 0004cfab-14fd-4e49-80ba-63a80b6bddd6 | NaN | NaN | NaN | NaN | 0 |
| 1 | 00313ee0-9eaa-42f4-b0ab-c148ed3241cd | NaN | NaN | NaN | NaN | 0 |
| 2 | 00322d4d-1c29-4943-afc9-b6754be640eb | NaN | NaN | NaN | NaN | 0 |
| 3 | 003d8fa0-6bf1-40ed-b54c-ac657f8495c5 | NaN | NaN | NaN | NaN | 0 |
| 4 | 00436515-870c-4b36-a041-de91049b9ab4 | 264.0 | 152.0 | 213.0 | 379.0 | 1 |
| ... | ... | ... | ... | ... | ... | ... |
| 30222 | c1ec14ff-f6d7-4b38-b0cb-fe07041cbdc8 | 185.0 | 298.0 | 228.0 | 379.0 | 1 |
| 30223 | c1edf42b-5958-47ff-a1e7-4f23d99583ba | NaN | NaN | NaN | NaN | 0 |
| 30224 | c1f6b555-2eb1-4231-98f6-50a963976431 | NaN | NaN | NaN | NaN | 0 |
| 30225 | c1f7889a-9ea9-4acb-b64c-b737c929599a | 570.0 | 393.0 | 261.0 | 345.0 | 1 |
| 30226 | c1f7889a-9ea9-4acb-b64c-b737c929599a | 233.0 | 424.0 | 201.0 | 356.0 | 1 |
30227 rows × 6 columns
print(train_df.info())
<class 'pandas.core.frame.DataFrame'> RangeIndex: 30227 entries, 0 to 30226 Data columns (total 6 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 patientId 30227 non-null object 1 x 9555 non-null float64 2 y 9555 non-null float64 3 width 9555 non-null float64 4 height 9555 non-null float64 5 Target 30227 non-null int64 dtypes: float64(4), int64(1), object(1) memory usage: 1.4+ MB None
def printwithinfoseparator(data,label):
print(f'--------====== {label} =====-----------')
print(data)
print(f'---------===========-----------')
#to understand the information
printwithinfoseparator(train_df['Target'].value_counts(),'Define by different target')
printwithinfoseparator(train_df[train_df['Target']== 0].isnull().sum(),'to check data with target 0 and not empty')
printwithinfoseparator(train_df[train_df['Target']== 1].isnull().sum(),'to check data with target 1 and not empty')
--------====== Define by different target =====----------- 0 20672 1 9555 Name: Target, dtype: int64 ---------===========----------- --------====== to check data with target 0 and not empty =====----------- patientId 0 x 20672 y 20672 width 20672 height 20672 Target 0 dtype: int64 ---------===========----------- --------====== to check data with target 1 and not empty =====----------- patientId 0 x 0 y 0 width 0 height 0 Target 0 dtype: int64 ---------===========-----------
printwithinfoseparator(len(train_df[train_df['Target']== 1]['patientId'].unique()),'count unique with TARGET 1 ')
printwithinfoseparator(len(train_df[train_df['Target']== 0]['patientId'].unique()),'count unique with TARGET 0 ')
--------====== count unique with TARGET 1 =====----------- 6012 ---------===========----------- --------====== count unique with TARGET 0 =====----------- 20672 ---------===========-----------
#if you have zip and not have unzipped then and then open it otherwise it will eat you 20 min.
## for train images zip
with zp.ZipFile("stage_2_train_images.zip","r") as zip_ref:
zip_ref.extractall("train_images")
# for test images zip
with zp.ZipFile("stage_2_test_images.zip","r") as zip_ref:
zip_ref.extractall("test_images")
#just extracted traine images file and dumped to list
images_df = os.listdir('train_images\stage_2_train_images')
printwithinfoseparator(len(images_df),'Total trained images found from zip ')
--------====== Total trained images found from zip =====----------- 26684 ---------===========-----------
print('double check time --> total unique patientid and total images found both numbers are same :) :D ')
double check time --> total unique patientid and total images found both numbers are same :) :D
images_test_df = os.listdir('test_images\stage_2_test_images')
printwithinfoseparator(len(images_test_df),'Total test images found from zip ')
--------====== Total test images found from zip =====----------- 3000 ---------===========-----------
#now checking with second detail class csv and dump into dataframe
df_class = pd.read_csv('stage_2_detailed_class_info.csv')
df_class.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 30227 entries, 0 to 30226 Data columns (total 2 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 patientId 30227 non-null object 1 class 30227 non-null object dtypes: object(2) memory usage: 472.4+ KB
#need to merge both our dataframe based on patient id and on inner join
mergedf= pd.merge(train_df, df_class, on="patientId")
#remove the duplicated rows
mergedf = mergedf.drop_duplicates()
mergedf
| patientId | x | y | width | height | Target | class | |
|---|---|---|---|---|---|---|---|
| 0 | 0004cfab-14fd-4e49-80ba-63a80b6bddd6 | NaN | NaN | NaN | NaN | 0 | No Lung Opacity / Not Normal |
| 1 | 00313ee0-9eaa-42f4-b0ab-c148ed3241cd | NaN | NaN | NaN | NaN | 0 | No Lung Opacity / Not Normal |
| 2 | 00322d4d-1c29-4943-afc9-b6754be640eb | NaN | NaN | NaN | NaN | 0 | No Lung Opacity / Not Normal |
| 3 | 003d8fa0-6bf1-40ed-b54c-ac657f8495c5 | NaN | NaN | NaN | NaN | 0 | Normal |
| 4 | 00436515-870c-4b36-a041-de91049b9ab4 | 264.0 | 152.0 | 213.0 | 379.0 | 1 | Lung Opacity |
| ... | ... | ... | ... | ... | ... | ... | ... |
| 37621 | c1ec14ff-f6d7-4b38-b0cb-fe07041cbdc8 | 185.0 | 298.0 | 228.0 | 379.0 | 1 | Lung Opacity |
| 37623 | c1edf42b-5958-47ff-a1e7-4f23d99583ba | NaN | NaN | NaN | NaN | 0 | Normal |
| 37624 | c1f6b555-2eb1-4231-98f6-50a963976431 | NaN | NaN | NaN | NaN | 0 | Normal |
| 37625 | c1f7889a-9ea9-4acb-b64c-b737c929599a | 570.0 | 393.0 | 261.0 | 345.0 | 1 | Lung Opacity |
| 37627 | c1f7889a-9ea9-4acb-b64c-b737c929599a | 233.0 | 424.0 | 201.0 | 356.0 | 1 | Lung Opacity |
30227 rows × 7 columns
'''define a function to change the type from object / catagorical to int '''
def changeType(x):
if x == 'No Lung Opacity / Not Normal':
return 2
elif x == 'Normal':
return 0
elif x == 'Lung Opacity':
return 1
# apply the function to class col
mergedf['class']=mergedf['class'].apply(changeType)
mergedf
| patientId | x | y | width | height | Target | class | |
|---|---|---|---|---|---|---|---|
| 0 | 0004cfab-14fd-4e49-80ba-63a80b6bddd6 | NaN | NaN | NaN | NaN | 0 | 2 |
| 1 | 00313ee0-9eaa-42f4-b0ab-c148ed3241cd | NaN | NaN | NaN | NaN | 0 | 2 |
| 2 | 00322d4d-1c29-4943-afc9-b6754be640eb | NaN | NaN | NaN | NaN | 0 | 2 |
| 3 | 003d8fa0-6bf1-40ed-b54c-ac657f8495c5 | NaN | NaN | NaN | NaN | 0 | 0 |
| 4 | 00436515-870c-4b36-a041-de91049b9ab4 | 264.0 | 152.0 | 213.0 | 379.0 | 1 | 1 |
| ... | ... | ... | ... | ... | ... | ... | ... |
| 37621 | c1ec14ff-f6d7-4b38-b0cb-fe07041cbdc8 | 185.0 | 298.0 | 228.0 | 379.0 | 1 | 1 |
| 37623 | c1edf42b-5958-47ff-a1e7-4f23d99583ba | NaN | NaN | NaN | NaN | 0 | 0 |
| 37624 | c1f6b555-2eb1-4231-98f6-50a963976431 | NaN | NaN | NaN | NaN | 0 | 0 |
| 37625 | c1f7889a-9ea9-4acb-b64c-b737c929599a | 570.0 | 393.0 | 261.0 | 345.0 | 1 | 1 |
| 37627 | c1f7889a-9ea9-4acb-b64c-b737c929599a | 233.0 | 424.0 | 201.0 | 356.0 | 1 | 1 |
30227 rows × 7 columns
#find the value count for the df
printwithinfoseparator(mergedf['class'].value_counts(),'merge dataframe with unique class and count')
# mergedf['class'].value_counts()
--------====== merge dataframe with unique class and count =====----------- 2 11821 1 9555 0 8851 Name: class, dtype: int64 ---------===========-----------
#to verify the data merge has class 1 and target 1 both have other labeling box data available
data_check = mergedf[(mergedf['class']== 1 )&( mergedf['Target'] ==1)]
data_check
| patientId | x | y | width | height | Target | class | |
|---|---|---|---|---|---|---|---|
| 4 | 00436515-870c-4b36-a041-de91049b9ab4 | 264.0 | 152.0 | 213.0 | 379.0 | 1 | 1 |
| 6 | 00436515-870c-4b36-a041-de91049b9ab4 | 562.0 | 152.0 | 256.0 | 453.0 | 1 | 1 |
| 10 | 00704310-78a8-4b38-8475-49f4573b2dbb | 323.0 | 577.0 | 160.0 | 104.0 | 1 | 1 |
| 12 | 00704310-78a8-4b38-8475-49f4573b2dbb | 695.0 | 575.0 | 162.0 | 137.0 | 1 | 1 |
| 18 | 00aecb01-a116-45a2-956c-08d2fa55433f | 288.0 | 322.0 | 94.0 | 135.0 | 1 | 1 |
| ... | ... | ... | ... | ... | ... | ... | ... |
| 37617 | c1e73a4e-7afe-4ec5-8af6-ce8315d7a2f2 | 316.0 | 504.0 | 179.0 | 273.0 | 1 | 1 |
| 37619 | c1ec14ff-f6d7-4b38-b0cb-fe07041cbdc8 | 609.0 | 464.0 | 240.0 | 284.0 | 1 | 1 |
| 37621 | c1ec14ff-f6d7-4b38-b0cb-fe07041cbdc8 | 185.0 | 298.0 | 228.0 | 379.0 | 1 | 1 |
| 37625 | c1f7889a-9ea9-4acb-b64c-b737c929599a | 570.0 | 393.0 | 261.0 | 345.0 | 1 | 1 |
| 37627 | c1f7889a-9ea9-4acb-b64c-b737c929599a | 233.0 | 424.0 | 201.0 | 356.0 | 1 | 1 |
9555 rows × 7 columns
#by data check info we can check is there any missing data or now so we can eliminate or manipulate further
data_check.info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 9555 entries, 4 to 37627 Data columns (total 7 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 patientId 9555 non-null object 1 x 9555 non-null float64 2 y 9555 non-null float64 3 width 9555 non-null float64 4 height 9555 non-null float64 5 Target 9555 non-null int64 6 class 9555 non-null int64 dtypes: float64(4), int64(2), object(1) memory usage: 597.2+ KB
printwithinfoseparator(len(data_check['patientId'].unique()),'value with unique patient id in target')
print('which sows that some patientid have more then one bounding box present')
--------====== value with unique patient id in target =====----------- 6012 ---------===========----------- which sows that some patientid have more then one bounding box present
#plot the class wise classification
plt.figure(figsize=(7,5),dpi=256)
fig,ax = plt.subplots(figsize=(7,5))
ax.bar(['No Lung Opacity/Not Normal','Lung Opacity','Normal'],mergedf['class'].value_counts().values,color=['orange','red','green'])
ax.tick_params(axis='x', rotation=15)
plt.xlabel('Class')
plt.ylabel('counts')
plt.title('Class wise data')
plt.show()
<Figure size 1792x1280 with 0 Axes>
#read images dicom and get the info
first_dicom_file = images_df[0]
first_dicom_file_path = os.path.join('train_images\\stage_2_train_images\\', first_dicom_file)
dcm = pdcm.dcmread(first_dicom_file_path)
dcm.fix_meta_info
<bound method Dataset.fix_meta_info of Dataset.file_meta ------------------------------- (0002, 0000) File Meta Information Group Length UL: 202 (0002, 0001) File Meta Information Version OB: b'\x00\x01' (0002, 0002) Media Storage SOP Class UID UI: Secondary Capture Image Storage (0002, 0003) Media Storage SOP Instance UID UI: 1.2.276.0.7230010.3.1.4.8323329.28530.1517874485.775526 (0002, 0010) Transfer Syntax UID UI: JPEG Baseline (Process 1) (0002, 0012) Implementation Class UID UI: 1.2.276.0.7230010.3.0.3.6.0 (0002, 0013) Implementation Version Name SH: 'OFFIS_DCMTK_360' ------------------------------------------------- (0008, 0005) Specific Character Set CS: 'ISO_IR 100' (0008, 0016) SOP Class UID UI: Secondary Capture Image Storage (0008, 0018) SOP Instance UID UI: 1.2.276.0.7230010.3.1.4.8323329.28530.1517874485.775526 (0008, 0020) Study Date DA: '19010101' (0008, 0030) Study Time TM: '000000.00' (0008, 0050) Accession Number SH: '' (0008, 0060) Modality CS: 'CR' (0008, 0064) Conversion Type CS: 'WSD' (0008, 0090) Referring Physician's Name PN: '' (0008, 103e) Series Description LO: 'view: PA' (0010, 0010) Patient's Name PN: '0004cfab-14fd-4e49-80ba-63a80b6bddd6' (0010, 0020) Patient ID LO: '0004cfab-14fd-4e49-80ba-63a80b6bddd6' (0010, 0030) Patient's Birth Date DA: '' (0010, 0040) Patient's Sex CS: 'F' (0010, 1010) Patient's Age AS: '51' (0018, 0015) Body Part Examined CS: 'CHEST' (0018, 5101) View Position CS: 'PA' (0020, 000d) Study Instance UID UI: 1.2.276.0.7230010.3.1.2.8323329.28530.1517874485.775525 (0020, 000e) Series Instance UID UI: 1.2.276.0.7230010.3.1.3.8323329.28530.1517874485.775524 (0020, 0010) Study ID SH: '' (0020, 0011) Series Number IS: '1' (0020, 0013) Instance Number IS: '1' (0020, 0020) Patient Orientation CS: '' (0028, 0002) Samples per Pixel US: 1 (0028, 0004) Photometric Interpretation CS: 'MONOCHROME2' (0028, 0010) Rows US: 1024 (0028, 0011) Columns US: 1024 (0028, 0030) Pixel Spacing DS: [0.14300000000000002, 0.14300000000000002] (0028, 0100) Bits Allocated US: 8 (0028, 0101) Bits Stored US: 8 (0028, 0102) High Bit US: 7 (0028, 0103) Pixel Representation US: 0 (0028, 2110) Lossy Image Compression CS: '01' (0028, 2114) Lossy Image Compression Method CS: 'ISO_10918_1' (7fe0, 0010) Pixel Data OB: Array of 142006 elements>
#just checking samples of train images
pne_check = data_check['patientId'].sample(2)
for pni in pne_check:
first_dicom_file_path = os.path.join('train_images\\stage_2_train_images\\', pni+'.dcm')
dcm = pdcm.dcmread(first_dicom_file_path)
plt.title(pni)
plt.axis =0
plt.imshow(dcm.pixel_array,cmap=plt.cm.binary) #used binary cmap
plt.show()
#try to check for the sharpanning images with sharpen filter
image_array = dcm.pixel_array
kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])
filtered_image =cv2.filter2D(image_array,-1,kernel)
plt.figure(figsize=(7,7),dpi=64)
plt.imshow((filtered_image),cmap=plt.cm.binary)
plt.show()
plt.figure(figsize=(7,7),dpi=64)
plt.imshow(dcm.pixel_array,cmap=plt.cm.binary)
<matplotlib.image.AxesImage at 0x2648a617fd0>
def createfolderifnot(path):
if not os.path.exists(path):
os.makedirs(path)
print(f'path create {path}')
path_image_train = 'train_images\\images_jpg'
createfolderifnot(path_image_train)
path_image_train512 = 'train_images\\images_512_jpg'
createfolderifnot(path_image_train512)
path_image_train256 = 'train_images\\images_256_jpg'
createfolderifnot(path_image_train256)
path_image_train128 = 'train_images\\images_128_jpg'
createfolderifnot(path_image_train128)
info_df = mergedf.copy()
total_images = info_df['patientId'].unique()
info_df['AGE'] = 0
info_df['SEX'] = 0
info_df['ViewPosition']=''
info_df['BodyPart'] = ''
info_df['glcm_contrast'] = ''
info_df['glcm_homogeneity'] = ''
info_df['glcm_energy'] = ''
info_df['glcm_correlation'] = ''
## loop for the image to get meta data for age sex body part and view position
for i in total_images:
path = f'train_images\\stage_2_train_images\\{i}.dcm'
if os.path.isfile(path):
first_dicom_file_path = os.path.join(path)
dcm_read = pdcm.dcmread(first_dicom_file_path)
img = Image.fromarray(dcm_read.pixel_array)
img.save(f'{path_image_train}\\{i}.jpg')
img2 = img.resize((512, 512))
img2.save(f'{path_image_train512}\\{i}.jpg')
img256 = img.resize((256, 256))
img256.save(f'{path_image_train256}\\{i}.jpg')
img128 = img.resize((128, 128))
img128.save(f'{path_image_train128}\\{i}.jpg')
image_array = np.array(img128)
# Example: Thresholding to segment lung regions
# threshold = -50 # Adjust threshold value based on DICOM pixel intensity range
# lung_mask = image_array < threshold
distances = [1, 2, 3] # Adjust distances based on image resolution
angles = [0, np.pi/4, np.pi/2, 3*np.pi/4]
glcm = graycomatrix(image_array.astype(np.uint8), distances, angles, symmetric=True, normed=True)
# print(glcm)
for il in info_df[info_df['patientId']== i].index:
# print(f'image done {il}')
info_df.loc[il,'AGE'] = dcm_read.PatientAge
info_df.loc[il,'SEX'] = 0 if dcm_read.PatientSex == 'F' else 1
info_df.loc[il,'BodyPart'] =dcm_read.BodyPartExamined
info_df.loc[il,'ViewPosition'] =dcm_read.ViewPosition
info_df.loc[il,'glcm_contrast'] = graycoprops(glcm, 'contrast').mean()
info_df.loc[il,'glcm_homogeneity'] = graycoprops(glcm, 'homogeneity').mean()
info_df.loc[il,'glcm_energy'] = graycoprops(glcm, 'energy').mean()
info_df.loc[il,'glcm_correlation'] = graycoprops(glcm, 'correlation').mean()
else:
print('nofile found ',i)
info_df.to_csv('infodf.csv')
info_df = pd.read_csv('infodf.csv')
info_df = info_df[info_df.columns[1:]]
info_df
| patientId | x | y | width | height | Target | class | AGE | SEX | ViewPosition | BodyPart | glcm_contrast | glcm_homogeneity | glcm_energy | glcm_correlation | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0004cfab-14fd-4e49-80ba-63a80b6bddd6 | NaN | NaN | NaN | NaN | 0 | 2 | 51 | 0 | PA | CHEST | 240.363107 | 0.221791 | 0.041201 | 0.977566 |
| 1 | 00313ee0-9eaa-42f4-b0ab-c148ed3241cd | NaN | NaN | NaN | NaN | 0 | 2 | 48 | 0 | PA | CHEST | 52.810114 | 0.333943 | 0.077472 | 0.983760 |
| 2 | 00322d4d-1c29-4943-afc9-b6754be640eb | NaN | NaN | NaN | NaN | 0 | 2 | 19 | 1 | AP | CHEST | 220.881035 | 0.200721 | 0.025836 | 0.968193 |
| 3 | 003d8fa0-6bf1-40ed-b54c-ac657f8495c5 | NaN | NaN | NaN | NaN | 0 | 0 | 28 | 1 | PA | CHEST | 406.426794 | 0.165048 | 0.019650 | 0.954598 |
| 4 | 00436515-870c-4b36-a041-de91049b9ab4 | 264.0 | 152.0 | 213.0 | 379.0 | 1 | 1 | 32 | 0 | AP | CHEST | 86.499986 | 0.236534 | 0.020687 | 0.986255 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 30222 | c1ec14ff-f6d7-4b38-b0cb-fe07041cbdc8 | 185.0 | 298.0 | 228.0 | 379.0 | 1 | 1 | 54 | 1 | AP | CHEST | 251.202459 | 0.243280 | 0.057668 | 0.932018 |
| 30223 | c1edf42b-5958-47ff-a1e7-4f23d99583ba | NaN | NaN | NaN | NaN | 0 | 0 | 46 | 0 | PA | CHEST | 139.894010 | 0.238966 | 0.074233 | 0.985241 |
| 30224 | c1f6b555-2eb1-4231-98f6-50a963976431 | NaN | NaN | NaN | NaN | 0 | 0 | 45 | 1 | PA | CHEST | 325.506092 | 0.212639 | 0.023197 | 0.924871 |
| 30225 | c1f7889a-9ea9-4acb-b64c-b737c929599a | 570.0 | 393.0 | 261.0 | 345.0 | 1 | 1 | 72 | 0 | AP | CHEST | 198.700831 | 0.227273 | 0.023604 | 0.973146 |
| 30226 | c1f7889a-9ea9-4acb-b64c-b737c929599a | 233.0 | 424.0 | 201.0 | 356.0 | 1 | 1 | 72 | 0 | AP | CHEST | 198.700831 | 0.227273 | 0.023604 | 0.973146 |
30227 rows × 15 columns
glcmcol = [ 'glcm_contrast', 'glcm_homogeneity','glcm_energy', 'glcm_correlation']
for i in glcmcol:
info_df[i] = pd.to_numeric(info_df[i])
info_df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 30227 entries, 0 to 30226 Data columns (total 15 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 patientId 30227 non-null object 1 x 9555 non-null float64 2 y 9555 non-null float64 3 width 9555 non-null float64 4 height 9555 non-null float64 5 Target 30227 non-null int64 6 class 30227 non-null int64 7 AGE 30227 non-null int64 8 SEX 30227 non-null int64 9 ViewPosition 30227 non-null object 10 BodyPart 30227 non-null object 11 glcm_contrast 30227 non-null float64 12 glcm_homogeneity 30227 non-null float64 13 glcm_energy 30227 non-null float64 14 glcm_correlation 30227 non-null float64 dtypes: float64(8), int64(4), object(3) memory usage: 3.5+ MB
info_df.describe(include='all')
| patientId | x | y | width | height | Target | class | AGE | SEX | ViewPosition | BodyPart | glcm_contrast | glcm_homogeneity | glcm_energy | glcm_correlation | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| count | 30227 | 9555.000000 | 9555.000000 | 9555.000000 | 9555.000000 | 30227.000000 | 30227.000000 | 30227.000000 | 30227.000000 | 30227 | 30227 | 30227.000000 | 30227.000000 | 30227.000000 | 30227.000000 |
| unique | 26684 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 2 | 1 | NaN | NaN | NaN | NaN |
| top | 3239951b-6211-4290-b237-3d9ad17176db | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | AP | CHEST | NaN | NaN | NaN | NaN |
| freq | 4 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 15297 | 30227 | NaN | NaN | NaN | NaN |
| mean | NaN | 394.047724 | 366.839560 | 218.471376 | 329.269702 | 0.316108 | 1.098257 | 46.797764 | 0.569557 | NaN | NaN | 247.026187 | 0.229017 | 0.041265 | 0.962661 |
| std | NaN | 204.574172 | 148.940488 | 59.289475 | 157.750755 | 0.464963 | 0.821133 | 16.892940 | 0.495146 | NaN | NaN | 136.758147 | 0.052652 | 0.044948 | 0.017100 |
| min | NaN | 2.000000 | 2.000000 | 40.000000 | 45.000000 | 0.000000 | 0.000000 | 1.000000 | 0.000000 | NaN | NaN | 15.571242 | 0.091079 | 0.012571 | 0.745418 |
| 25% | NaN | 207.000000 | 249.000000 | 177.000000 | 203.000000 | 0.000000 | 0.000000 | 34.000000 | 0.000000 | NaN | NaN | 143.653314 | 0.193911 | 0.022976 | 0.954354 |
| 50% | NaN | 324.000000 | 365.000000 | 217.000000 | 298.000000 | 0.000000 | 1.000000 | 49.000000 | 1.000000 | NaN | NaN | 228.389563 | 0.222584 | 0.028748 | 0.965842 |
| 75% | NaN | 594.000000 | 478.500000 | 259.000000 | 438.000000 | 1.000000 | 2.000000 | 59.000000 | 1.000000 | NaN | NaN | 321.095833 | 0.255714 | 0.041918 | 0.974290 |
| max | NaN | 835.000000 | 881.000000 | 528.000000 | 942.000000 | 1.000000 | 2.000000 | 155.000000 | 1.000000 | NaN | NaN | 1506.355794 | 0.733597 | 0.686796 | 0.996324 |
sns.pairplot(data=info_df)
<seaborn.axisgrid.PairGrid at 0x2648a655160>
for i in glcmcol:
plt.title(f'box plot for {i}')
sns.boxplot(data=info_df,x='Target',y=i)
plt.show()
targetcols = ['Target','SEX','glcm_contrast', 'glcm_homogeneity','glcm_energy', 'glcm_correlation']
df_cor = info_df[targetcols]
sns.heatmap(data=df_cor.corr(),cmap=plt.cm.Blues,annot=True)
<AxesSubplot:>
printwithinfoseparator(info_df['BodyPart'].value_counts(),'body part value uniqueness check')
printwithinfoseparator(info_df['ViewPosition'].value_counts(),'view position value uniqueness check')
printwithinfoseparator(info_df['SEX'].value_counts(),'Sex value uniqueness check')
--------====== body part value uniqueness check =====----------- CHEST 30227 Name: BodyPart, dtype: int64 ---------===========----------- --------====== view position value uniqueness check =====----------- AP 15297 PA 14930 Name: ViewPosition, dtype: int64 ---------===========----------- --------====== Sex value uniqueness check =====----------- 1 17216 0 13011 Name: SEX, dtype: int64 ---------===========-----------
info_df['AGE'].describe()
count 30227.000000 mean 46.797764 std 16.892940 min 1.000000 25% 34.000000 50% 49.000000 75% 59.000000 max 155.000000 Name: AGE, dtype: float64
info_df_512 = info_df.copy()
size = 512
def calculatetheimageboundings(x):
mainsize = 1024
# print(x)
if x > 0:
divider = mainsize//size
# print(divider)
_x = x//divider
# print(_x)
return _x
size=512
info_df_512['x'] = info_df_512['x'].apply(calculatetheimageboundings)
info_df_512['y'] = info_df_512['y'].apply(calculatetheimageboundings)
info_df_512['width'] = info_df_512['width'].apply(calculatetheimageboundings)
info_df_512['height'] = info_df_512['height'].apply(calculatetheimageboundings)
info_df_512
| patientId | x | y | width | height | Target | class | AGE | SEX | ViewPosition | BodyPart | glcm_contrast | glcm_homogeneity | glcm_energy | glcm_correlation | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0004cfab-14fd-4e49-80ba-63a80b6bddd6 | NaN | NaN | NaN | NaN | 0 | 2 | 51 | 0 | PA | CHEST | 240.363107 | 0.221791 | 0.041201 | 0.977566 |
| 1 | 00313ee0-9eaa-42f4-b0ab-c148ed3241cd | NaN | NaN | NaN | NaN | 0 | 2 | 48 | 0 | PA | CHEST | 52.810114 | 0.333943 | 0.077472 | 0.983760 |
| 2 | 00322d4d-1c29-4943-afc9-b6754be640eb | NaN | NaN | NaN | NaN | 0 | 2 | 19 | 1 | AP | CHEST | 220.881035 | 0.200721 | 0.025836 | 0.968193 |
| 3 | 003d8fa0-6bf1-40ed-b54c-ac657f8495c5 | NaN | NaN | NaN | NaN | 0 | 0 | 28 | 1 | PA | CHEST | 406.426794 | 0.165048 | 0.019650 | 0.954598 |
| 4 | 00436515-870c-4b36-a041-de91049b9ab4 | 132.0 | 76.0 | 106.0 | 189.0 | 1 | 1 | 32 | 0 | AP | CHEST | 86.499986 | 0.236534 | 0.020687 | 0.986255 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 30222 | c1ec14ff-f6d7-4b38-b0cb-fe07041cbdc8 | 92.0 | 149.0 | 114.0 | 189.0 | 1 | 1 | 54 | 1 | AP | CHEST | 251.202459 | 0.243280 | 0.057668 | 0.932018 |
| 30223 | c1edf42b-5958-47ff-a1e7-4f23d99583ba | NaN | NaN | NaN | NaN | 0 | 0 | 46 | 0 | PA | CHEST | 139.894010 | 0.238966 | 0.074233 | 0.985241 |
| 30224 | c1f6b555-2eb1-4231-98f6-50a963976431 | NaN | NaN | NaN | NaN | 0 | 0 | 45 | 1 | PA | CHEST | 325.506092 | 0.212639 | 0.023197 | 0.924871 |
| 30225 | c1f7889a-9ea9-4acb-b64c-b737c929599a | 285.0 | 196.0 | 130.0 | 172.0 | 1 | 1 | 72 | 0 | AP | CHEST | 198.700831 | 0.227273 | 0.023604 | 0.973146 |
| 30226 | c1f7889a-9ea9-4acb-b64c-b737c929599a | 116.0 | 212.0 | 100.0 | 178.0 | 1 | 1 | 72 | 0 | AP | CHEST | 198.700831 | 0.227273 | 0.023604 | 0.973146 |
30227 rows × 15 columns
# function to draw bounding Box on images
def get_bb(imag,data_lab,patid):
for i in range(len(data_lab)):
if data_lab.iloc[i]['patientId']==patid and data_lab.iloc[i]['Target']==1:
x= int(data_lab.iloc[i]['x'])
y= int(data_lab.iloc[i]['y'])
w= int(data_lab.iloc[i]['width'])
h= int(data_lab.iloc[i]['height'])
bb=cv2.rectangle(imag,(x,y),(x+w,y+h),(255,0,0),3)
plt.imshow(bb,cmap=plt.cm.binary)
elif data_lab.iloc[i]['patientId']==patid and data_lab.iloc[i]['Target']==0:
plt.imshow(imag,cmap=plt.cm.binary)
plt.show()
patid_ref = info_df[info_df['Target'] == 1]['patientId'].sample(5)
patid_ref
3821 3ae783bc-9fd3-4e66-b9cd-101a43f122bd 19470 b4abc0a4-600c-4834-bd71-c9dbb21eaaf0 24683 ddb757d1-a6e2-42e3-a438-100006fb38dd 20303 ba452891-fb43-48bf-9019-855556b48f91 18370 ad7bfead-6c0b-436f-9d0b-92827be703c3 Name: patientId, dtype: object
for i in patid_ref:
img1= cv2.imread(f'train_images\images_jpg\{i}.jpg')
get_bb(img1,info_df,i)
for i in patid_ref:
img1= cv2.imread(f'train_images\images_512_jpg\{i}.jpg')
get_bb(img1,info_df_512,i)
sns.set(style="whitegrid")
# Create the countplot
plt.figure(figsize=(10, 6))
sns.countplot(x='Target', hue='class', data=info_df)
plt.title('Relationship Between Class and Target')
plt.xlabel('Target')
plt.ylabel('Count')
plt.legend(title='Class')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
sns.set(style="whitegrid")
# Create the countplot
plt.figure(figsize=(10, 6))
sns.countplot(x='Target', hue='SEX', data=info_df)
plt.title('Relationship Between Sex and Target')
plt.xlabel('Target')
plt.ylabel('Count')
plt.legend(title='Class')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
lung_opacity_data = info_df[info_df['Target'] == 1]
# Plotting
plt.figure(figsize=(12, 8))
plt.subplots_adjust(hspace=0.5)
plt.subplot(2, 2, 1)
sns.kdeplot(data=lung_opacity_data, x='x', shade=True, color='blue')
plt.title('Density of x')
plt.subplot(2, 2, 2)
sns.kdeplot(data=lung_opacity_data, x='y', shade=True, color='green')
plt.title('Density of y')
plt.subplot(2, 2, 3)
sns.kdeplot(data=lung_opacity_data, x='width', shade=True, color='orange')
plt.title('Density of width')
plt.subplot(2, 2, 4)
sns.kdeplot(data=lung_opacity_data, x='height', shade=True, color='red')
plt.title('Density of height')
plt.show()
C:\Users\JAYPAT~1\AppData\Local\Temp/ipykernel_25200/2878436323.py:8: FutureWarning: `shade` is now deprecated in favor of `fill`; setting `fill=True`. This will become an error in seaborn v0.14.0; please update your code. sns.kdeplot(data=lung_opacity_data, x='x', shade=True, color='blue') C:\Users\JAYPAT~1\AppData\Local\Temp/ipykernel_25200/2878436323.py:12: FutureWarning: `shade` is now deprecated in favor of `fill`; setting `fill=True`. This will become an error in seaborn v0.14.0; please update your code. sns.kdeplot(data=lung_opacity_data, x='y', shade=True, color='green') C:\Users\JAYPAT~1\AppData\Local\Temp/ipykernel_25200/2878436323.py:16: FutureWarning: `shade` is now deprecated in favor of `fill`; setting `fill=True`. This will become an error in seaborn v0.14.0; please update your code. sns.kdeplot(data=lung_opacity_data, x='width', shade=True, color='orange') C:\Users\JAYPAT~1\AppData\Local\Temp/ipykernel_25200/2878436323.py:20: FutureWarning: `shade` is now deprecated in favor of `fill`; setting `fill=True`. This will become an error in seaborn v0.14.0; please update your code. sns.kdeplot(data=lung_opacity_data, x='height', shade=True, color='red')
ax= plt.figure(figsize=(10,7),dpi=64)
info_df.hist(ax=ax)
C:\Users\JAYPAT~1\AppData\Local\Temp/ipykernel_25200/2122389849.py:2: UserWarning: To output multiple subplots, the figure containing the passed axes is being cleared. info_df.hist(ax=ax)
array([[<AxesSubplot:title={'center':'x'}>,
<AxesSubplot:title={'center':'y'}>,
<AxesSubplot:title={'center':'width'}>],
[<AxesSubplot:title={'center':'height'}>,
<AxesSubplot:title={'center':'Target'}>,
<AxesSubplot:title={'center':'class'}>],
[<AxesSubplot:title={'center':'AGE'}>,
<AxesSubplot:title={'center':'SEX'}>,
<AxesSubplot:title={'center':'glcm_contrast'}>],
[<AxesSubplot:title={'center':'glcm_homogeneity'}>,
<AxesSubplot:title={'center':'glcm_energy'}>,
<AxesSubplot:title={'center':'glcm_correlation'}>]], dtype=object)
# Assuming df is your DataFrame containing the 'Target' column
target_counts = info_df['class'].value_counts()
# Plotting the distribution as a pie chart
plt.figure(figsize=(8, 8))
plt.pie(target_counts, labels=target_counts.index, autopct='%1.1f%%', colors=['yellow', 'red','green'])
plt.title('Distribution of Targets')
plt.show()
pos_bbox = info_df.query('Target==1')
pos_bbox.plot.scatter(x='x', y='y')
pos_bbox.plot.scatter(x='x', y='height')
pos_bbox.plot.scatter(x='x', y='width')
<AxesSubplot:xlabel='x', ylabel='width'>
plt.figure(figsize=(2,2))
sns.pairplot(data=info_df)
<seaborn.axisgrid.PairGrid at 0x2649c73a310>
<Figure size 144x144 with 0 Axes>
def agetocatagory(age):
age = int(age)
if age >= 1 and age <= 13:
return 'child'
elif age >= 14 and age <=19:
return 'teenage'
elif age >=20 and age <=45:
return 'Young'
elif age >=46 and age <=60:
return 'old'
elif age >=61:
return 'vold'
info_df['agecat'] =''
info_df['agecat'] = info_df['AGE'].apply(agetocatagory)
#for checkign based on target and sex wise age catagory
info_df.groupby(['Target','SEX'])['agecat'].value_counts()
Target SEX agecat
0 0 Young 3410
old 3240
vold 1916
teenage 252
child 198
1 old 4109
Young 4009
vold 2802
teenage 451
child 285
1 0 Young 1488
old 1405
vold 812
child 147
teenage 143
1 Young 2246
old 1735
vold 1122
teenage 248
child 209
Name: agecat, dtype: int64
plt.figure(figsize=(10, 6))
sns.countplot(x='Target', hue='agecat', data=info_df)
plt.title('Relationship Between age catagory and Target')
Text(0.5, 1.0, 'Relationship Between age catagory and Target')
# Assuming df is your DataFrame containing the 'Target' column
target_counts = info_df.query('Target ==0')['agecat'].value_counts()
# Plotting the distribution as a pie chart
plt.figure(figsize=(8, 8))
plt.pie(target_counts, labels=target_counts.index, autopct='%1.1f%%')
plt.title('Distribution of Targets')
plt.show()
target_counts = info_df.query('Target ==1')['agecat'].value_counts()
# Plotting the distribution as a pie chart
plt.figure(figsize=(8, 8))
plt.pie(target_counts, labels=target_counts.index, autopct='%1.1f%%')
plt.title('Distribution of Targets')
plt.show()
size = 256
info_df_256 = info_df.copy()
info_df_256['x'] = info_df_256['x'].apply(calculatetheimageboundings)
info_df_256['y'] = info_df_256['y'].apply(calculatetheimageboundings)
info_df_256['width'] = info_df_256['width'].apply(calculatetheimageboundings)
info_df_256['height'] = info_df_256['height'].apply(calculatetheimageboundings)
info_df_256
| patientId | x | y | width | height | Target | class | AGE | SEX | ViewPosition | BodyPart | glcm_contrast | glcm_homogeneity | glcm_energy | glcm_correlation | agecat | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0004cfab-14fd-4e49-80ba-63a80b6bddd6 | NaN | NaN | NaN | NaN | 0 | 2 | 51 | 0 | PA | CHEST | 240.363107 | 0.221791 | 0.041201 | 0.977566 | old |
| 1 | 00313ee0-9eaa-42f4-b0ab-c148ed3241cd | NaN | NaN | NaN | NaN | 0 | 2 | 48 | 0 | PA | CHEST | 52.810114 | 0.333943 | 0.077472 | 0.983760 | old |
| 2 | 00322d4d-1c29-4943-afc9-b6754be640eb | NaN | NaN | NaN | NaN | 0 | 2 | 19 | 1 | AP | CHEST | 220.881035 | 0.200721 | 0.025836 | 0.968193 | teenage |
| 3 | 003d8fa0-6bf1-40ed-b54c-ac657f8495c5 | NaN | NaN | NaN | NaN | 0 | 0 | 28 | 1 | PA | CHEST | 406.426794 | 0.165048 | 0.019650 | 0.954598 | Young |
| 4 | 00436515-870c-4b36-a041-de91049b9ab4 | 66.0 | 38.0 | 53.0 | 94.0 | 1 | 1 | 32 | 0 | AP | CHEST | 86.499986 | 0.236534 | 0.020687 | 0.986255 | Young |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 30222 | c1ec14ff-f6d7-4b38-b0cb-fe07041cbdc8 | 46.0 | 74.0 | 57.0 | 94.0 | 1 | 1 | 54 | 1 | AP | CHEST | 251.202459 | 0.243280 | 0.057668 | 0.932018 | old |
| 30223 | c1edf42b-5958-47ff-a1e7-4f23d99583ba | NaN | NaN | NaN | NaN | 0 | 0 | 46 | 0 | PA | CHEST | 139.894010 | 0.238966 | 0.074233 | 0.985241 | old |
| 30224 | c1f6b555-2eb1-4231-98f6-50a963976431 | NaN | NaN | NaN | NaN | 0 | 0 | 45 | 1 | PA | CHEST | 325.506092 | 0.212639 | 0.023197 | 0.924871 | Young |
| 30225 | c1f7889a-9ea9-4acb-b64c-b737c929599a | 142.0 | 98.0 | 65.0 | 86.0 | 1 | 1 | 72 | 0 | AP | CHEST | 198.700831 | 0.227273 | 0.023604 | 0.973146 | vold |
| 30226 | c1f7889a-9ea9-4acb-b64c-b737c929599a | 58.0 | 106.0 | 50.0 | 89.0 | 1 | 1 | 72 | 0 | AP | CHEST | 198.700831 | 0.227273 | 0.023604 | 0.973146 | vold |
30227 rows × 16 columns
#for getting just 1000 images from each classes
target_not_phe = info_df_256[info_df_256['class']==0].sample(1000)
target_not_phe_not_op = info_df_256[info_df_256['class']==2].sample(1000)
target_phe =info_df_256[info_df_256['class']==1].sample(1000)
combine_model_df_1k = pd.concat([target_not_phe,target_phe,target_not_phe_not_op],axis=0)
combine_model_df_1k.reset_index(drop=True)
combine_model_df_1k
| patientId | x | y | width | height | Target | class | AGE | SEX | ViewPosition | BodyPart | glcm_contrast | glcm_homogeneity | glcm_energy | glcm_correlation | agecat | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 17269 | a551cd16-3064-4204-8410-86831370ad61 | NaN | NaN | NaN | NaN | 0 | 0 | 50 | 1 | PA | CHEST | 306.593503 | 0.174920 | 0.019247 | 0.948594 | old |
| 24083 | d87efba3-87d4-4f09-95a0-f927a1a22df7 | NaN | NaN | NaN | NaN | 0 | 0 | 39 | 1 | PA | CHEST | 215.309888 | 0.174258 | 0.019767 | 0.941859 | Young |
| 6519 | 4f843afa-f88f-4a85-8365-87ab781fae79 | NaN | NaN | NaN | NaN | 0 | 0 | 59 | 1 | PA | CHEST | 390.651282 | 0.155675 | 0.016292 | 0.947248 | old |
| 193 | 05d3b194-78bb-4fe9-aa1c-0f1d76e5641d | NaN | NaN | NaN | NaN | 0 | 0 | 45 | 0 | PA | CHEST | 434.578427 | 0.223216 | 0.087301 | 0.951282 | Young |
| 2454 | 320e8587-ab3c-47d0-9a89-fcc2f5cb5c95 | NaN | NaN | NaN | NaN | 0 | 0 | 42 | 1 | PA | CHEST | 214.158519 | 0.196748 | 0.047265 | 0.977092 | Young |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 13088 | 8413612c-f9e8-42de-b3a3-bb636a6f0730 | NaN | NaN | NaN | NaN | 0 | 2 | 55 | 0 | AP | CHEST | 247.435742 | 0.294478 | 0.034365 | 0.963647 | old |
| 22043 | c7b538c8-e32c-446b-bc21-49b7decacd84 | NaN | NaN | NaN | NaN | 0 | 2 | 52 | 0 | PA | CHEST | 783.892339 | 0.206074 | 0.036035 | 0.920074 | old |
| 20992 | beaac9d6-d4b5-474f-9e32-06655242e973 | NaN | NaN | NaN | NaN | 0 | 2 | 47 | 1 | PA | CHEST | 283.473674 | 0.202902 | 0.022334 | 0.964803 | old |
| 5725 | 4923a208-0341-4b6f-b355-3c537a3fd7d1 | NaN | NaN | NaN | NaN | 0 | 2 | 65 | 1 | PA | CHEST | 405.186756 | 0.193284 | 0.018976 | 0.953590 | vold |
| 16461 | 9f3893a1-3983-461c-a04f-f8701d4668ee | NaN | NaN | NaN | NaN | 0 | 2 | 55 | 1 | AP | CHEST | 139.559941 | 0.258193 | 0.033607 | 0.979692 | old |
3000 rows × 16 columns
from sklearn.model_selection import train_test_split
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.models import Sequential,Model
from tensorflow.keras.layers import Conv2D,GlobalAveragePooling2D ,MaxPooling2D, Flatten, Dense, Dropout
from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping
# Define image dimensions and batch size
img_width, img_height = 256, 256
batch_size = 32
# Define the directory where the images are stored
image_directory = 'train_images/images_256_jpg'
# Assuming combine_model_df_1k contains the dataset with patientId and corresponding labels
# Convert numerical class labels to string representations
combine_model_df_1k['class'] = combine_model_df_1k['class'].astype(str)
combine_model_df_1k['patientId'] = combine_model_df_1k['patientId'] + '.jpg'
# Split the dataset into training and validation sets
train_df, val_df = train_test_split(combine_model_df_1k, test_size=0.2, random_state=77)
epocs_count = 25
datagen = ImageDataGenerator(rescale=1./255, validation_split=0.2)
train_generator = datagen.flow_from_dataframe(
dataframe=train_df,
directory=image_directory,
x_col="patientId", # Use the column name for file paths
y_col="class", # Use the column name for labels
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode='categorical',
subset='training'
)
validation_generator = datagen.flow_from_dataframe(
dataframe=val_df,
directory=image_directory,
x_col="patientId", # Use the column name for file paths
y_col="class", # Use the column name for labels
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode='categorical',
subset='validation'
)
model_cnn_1 = Sequential()
model_cnn_1.add(Conv2D(9,(3,3),activation='relu',input_shape = (img_width,img_height,1)))
model_cnn_1.add(MaxPooling2D((2,2)))
model_cnn_1.add(Conv2D(16,(3,3),activation='relu'))
model_cnn_1.add(MaxPooling2D((2,2)))
model_cnn_1.add(Conv2D(32,(3,3),activation='relu'))
model_cnn_1.add(MaxPooling2D((2,2)))
# model_cnn_1.add(GlobalAveragePooling2D())
model_cnn_1.add(Flatten())
model_cnn_1.add(Dense(128,activation='relu'))
model_cnn_1.add(Dropout(0.4))
model_cnn_1.add(Dense(64,activation='relu'))
model_cnn_1.add(Dropout(0.5))
model_cnn_1.add(Dense(3,activation='softmax'))
# Compile the model_cnn_1
model_cnn_1.compile(optimizer='adam',
loss='categorical_crossentropy', # Use categorical cross-entropy for multi-class classification
metrics=['accuracy'],)
# Define callbacks
checkpoint = ModelCheckpoint("best_model.h5", monitor='val_accuracy', verbose=1, save_best_only=True, mode='max')
early_stopping = EarlyStopping(monitor='val_accuracy', patience=5, verbose=1, restore_best_weights=True)
# Train the model
history = model_cnn_1.fit(
train_generator,
steps_per_epoch=train_generator.samples // batch_size,
epochs=epocs_count,
validation_data=validation_generator,
validation_steps=validation_generator.samples // batch_size,
callbacks=[checkpoint, early_stopping]
)
Found 1920 validated image filenames belonging to 3 classes. Found 120 validated image filenames belonging to 3 classes. Epoch 1/25 60/60 [==============================] - ETA: 0s - loss: 1.1098 - accuracy: 0.3865 Epoch 1: val_accuracy improved from -inf to 0.66667, saving model to best_model.h5 60/60 [==============================] - 38s 543ms/step - loss: 1.1098 - accuracy: 0.3865 - val_loss: 0.9685 - val_accuracy: 0.6667 Epoch 2/25 60/60 [==============================] - ETA: 0s - loss: 0.9645 - accuracy: 0.5245 Epoch 2: val_accuracy did not improve from 0.66667 60/60 [==============================] - 3s 49ms/step - loss: 0.9645 - accuracy: 0.5245 - val_loss: 0.9076 - val_accuracy: 0.5833 Epoch 3/25 59/60 [============================>.] - ETA: 0s - loss: 0.9272 - accuracy: 0.5514 Epoch 3: val_accuracy did not improve from 0.66667 60/60 [==============================] - 3s 48ms/step - loss: 0.9277 - accuracy: 0.5495 - val_loss: 0.9207 - val_accuracy: 0.5625 Epoch 4/25 60/60 [==============================] - ETA: 0s - loss: 0.9039 - accuracy: 0.5573 Epoch 4: val_accuracy did not improve from 0.66667 60/60 [==============================] - 3s 48ms/step - loss: 0.9039 - accuracy: 0.5573 - val_loss: 0.8900 - val_accuracy: 0.5625 Epoch 5/25 59/60 [============================>.] - ETA: 0s - loss: 0.8865 - accuracy: 0.5805 Epoch 5: val_accuracy did not improve from 0.66667 60/60 [==============================] - 3s 48ms/step - loss: 0.8856 - accuracy: 0.5802 - val_loss: 0.8851 - val_accuracy: 0.6042 Epoch 6/25 59/60 [============================>.] - ETA: 0s - loss: 0.8437 - accuracy: 0.5953 Epoch 6: val_accuracy improved from 0.66667 to 0.69792, saving model to best_model.h5 60/60 [==============================] - 3s 55ms/step - loss: 0.8427 - accuracy: 0.5938 - val_loss: 0.8435 - val_accuracy: 0.6979 Epoch 7/25 59/60 [============================>.] - ETA: 0s - loss: 0.8448 - accuracy: 0.6022 Epoch 7: val_accuracy did not improve from 0.69792 60/60 [==============================] - 3s 48ms/step - loss: 0.8428 - accuracy: 0.6047 - val_loss: 0.8593 - val_accuracy: 0.6250 Epoch 8/25 60/60 [==============================] - ETA: 0s - loss: 0.7866 - accuracy: 0.6297 Epoch 8: val_accuracy did not improve from 0.69792 60/60 [==============================] - 3s 49ms/step - loss: 0.7866 - accuracy: 0.6297 - val_loss: 0.9076 - val_accuracy: 0.6458 Epoch 9/25 59/60 [============================>.] - ETA: 0s - loss: 0.7627 - accuracy: 0.6404 Epoch 9: val_accuracy did not improve from 0.69792 60/60 [==============================] - 3s 48ms/step - loss: 0.7640 - accuracy: 0.6427 - val_loss: 0.8915 - val_accuracy: 0.5625 Epoch 10/25 60/60 [==============================] - ETA: 0s - loss: 0.7068 - accuracy: 0.6776 Epoch 10: val_accuracy did not improve from 0.69792 60/60 [==============================] - 3s 49ms/step - loss: 0.7068 - accuracy: 0.6776 - val_loss: 0.8808 - val_accuracy: 0.5417 Epoch 11/25 60/60 [==============================] - ETA: 0s - loss: 0.6653 - accuracy: 0.6943 Epoch 11: val_accuracy did not improve from 0.69792 Restoring model weights from the end of the best epoch: 6. 60/60 [==============================] - 3s 48ms/step - loss: 0.6653 - accuracy: 0.6943 - val_loss: 1.1052 - val_accuracy: 0.5938 Epoch 11: early stopping
train_acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
train_loss = history.history['loss']
val_loss = history.history['val_loss']
# Create separate plots for accuracy and loss
plt.figure(figsize=(10, 5))
# Accuracy plot
plt.subplot(121)
plt.plot(train_acc, label='Training Accuracy')
plt.plot(val_acc, label='Validation Accuracy')
plt.title('Model Accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
# Loss plot
plt.subplot(122)
plt.plot(train_loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.title('Model Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.tight_layout()
plt.show()
#for getting just 2000 images from each classes
target_not_phe = info_df_256[info_df_256['class']==0].sample(2000)
target_not_phe_not_op = info_df_256[info_df_256['class']==2].sample(2000)
target_phe =info_df_256[info_df_256['class']==1].sample(2000)
combine_model_df_2k = pd.concat([target_not_phe,target_phe,target_not_phe_not_op],axis=0)
combine_model_df_2k.reset_index(drop=True)
combine_model_df_2k
| patientId | x | y | width | height | Target | class | AGE | SEX | ViewPosition | BodyPart | glcm_contrast | glcm_homogeneity | glcm_energy | glcm_correlation | agecat | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 502 | 08226aab-e8d2-401f-8b8d-1a2a51234c42 | NaN | NaN | NaN | NaN | 0 | 0 | 47 | 1 | PA | CHEST | 266.354325 | 0.183644 | 0.027495 | 0.970958 | old |
| 21412 | c3146b7e-b141-4f08-84f2-e9c8d88674df | NaN | NaN | NaN | NaN | 0 | 0 | 74 | 1 | PA | CHEST | 175.901242 | 0.213648 | 0.023234 | 0.965742 | vold |
| 14525 | 8f66472e-29c1-4dc5-86d7-8e0fa67e9f74 | NaN | NaN | NaN | NaN | 0 | 0 | 47 | 1 | PA | CHEST | 200.984357 | 0.174193 | 0.019557 | 0.954713 | old |
| 24098 | d8adf370-83b9-4852-bedd-6e180fb95d9b | NaN | NaN | NaN | NaN | 0 | 0 | 68 | 1 | PA | CHEST | 471.939189 | 0.210893 | 0.021338 | 0.941308 | vold |
| 12842 | 820a9541-f7cf-4b39-ab04-6d1befbd0835 | NaN | NaN | NaN | NaN | 0 | 0 | 67 | 1 | AP | CHEST | 214.742998 | 0.285640 | 0.038926 | 0.964955 | vold |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 4657 | 405fc22f-ea3f-481e-bb8e-b6b75ce9b916 | NaN | NaN | NaN | NaN | 0 | 2 | 28 | 0 | PA | CHEST | 194.378827 | 0.217663 | 0.046316 | 0.981116 | Young |
| 5827 | 49f711da-4bb0-4309-aeac-d18fbfa83f98 | NaN | NaN | NaN | NaN | 0 | 2 | 76 | 0 | PA | CHEST | 522.260975 | 0.278276 | 0.053782 | 0.950705 | vold |
| 15437 | 96ed9839-9487-4700-bff1-d56aca5c00e2 | NaN | NaN | NaN | NaN | 0 | 2 | 72 | 1 | AP | CHEST | 80.921843 | 0.264735 | 0.028101 | 0.976821 | vold |
| 25876 | e7488964-cda3-45b3-8dac-52c21148ff29 | NaN | NaN | NaN | NaN | 0 | 2 | 28 | 1 | AP | CHEST | 106.707369 | 0.246364 | 0.025374 | 0.976472 | Young |
| 23409 | d2b23fd5-ad90-4768-95d5-7463fc4bac84 | NaN | NaN | NaN | NaN | 0 | 2 | 63 | 1 | PA | CHEST | 335.348917 | 0.245548 | 0.027962 | 0.954386 | vold |
6000 rows × 16 columns
combine_model_df_2k['class'] = combine_model_df_2k['class'].astype(str)
combine_model_df_2k['patientId'] = combine_model_df_2k['patientId'] + '.jpg'
# Split the dataset into training and validation sets
train_df2, val_df2 = train_test_split(combine_model_df_2k, test_size=0.2, random_state=77)
epocs_count = 30
datagen = ImageDataGenerator(rescale=1./255, validation_split=0.2)
train_generator = datagen.flow_from_dataframe(
dataframe=train_df2,
directory=image_directory,
x_col="patientId", # Use the column name for file paths
y_col="class", # Use the column name for labels
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode='categorical',
subset='training'
)
validation_generator = datagen.flow_from_dataframe(
dataframe=val_df2,
directory=image_directory,
x_col="patientId", # Use the column name for file paths
y_col="class", # Use the column name for labels
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode='categorical',
subset='validation'
)
model_cnn_2_k256 = Sequential()
model_cnn_2_k256.add(Conv2D(9,(3,3),activation='relu',input_shape = (img_width,img_height,1)))
model_cnn_2_k256.add(MaxPooling2D((2,2)))
model_cnn_2_k256.add(Conv2D(16,(3,3),activation='relu'))
model_cnn_2_k256.add(MaxPooling2D((2,2)))
model_cnn_2_k256.add(Conv2D(8,(3,3),activation='relu'))
model_cnn_2_k256.add(MaxPooling2D((2,2)))
model_cnn_2_k256.add(Flatten())
model_cnn_2_k256.add(Dense(64,activation='relu'))
model_cnn_2_k256.add(Dropout(0.5))
model_cnn_2_k256.add(Dense(16,activation='relu'))
model_cnn_2_k256.add(Dense(3,activation='softmax'))
# Compile the model_cnn_2_k256
model_cnn_2_k256.compile(optimizer='adam',
loss='categorical_crossentropy', # Use categorical cross-entropy for multi-class classification
metrics=['accuracy'],)
# Define callbacks
checkpoint = ModelCheckpoint("best_model.h5", monitor='val_accuracy', verbose=1, save_best_only=True, mode='max')
early_stopping = EarlyStopping(monitor='val_accuracy', patience=15, verbose=1, restore_best_weights=True)
# Train the model
history = model_cnn_2_k256.fit(
train_generator,
steps_per_epoch=train_generator.samples // batch_size,
epochs=epocs_count,
validation_data=validation_generator,
validation_steps=validation_generator.samples // batch_size,
callbacks=[checkpoint, early_stopping]
)
Found 3840 validated image filenames belonging to 3 classes. Found 240 validated image filenames belonging to 3 classes. Epoch 1/30 120/120 [==============================] - ETA: 0s - loss: 1.0239 - accuracy: 0.4599 Epoch 1: val_accuracy improved from -inf to 0.57143, saving model to best_model.h5 120/120 [==============================] - 58s 481ms/step - loss: 1.0239 - accuracy: 0.4599 - val_loss: 0.9141 - val_accuracy: 0.5714 Epoch 2/30 120/120 [==============================] - ETA: 0s - loss: 0.9271 - accuracy: 0.5562 Epoch 2: val_accuracy improved from 0.57143 to 0.61161, saving model to best_model.h5 120/120 [==============================] - 6s 48ms/step - loss: 0.9271 - accuracy: 0.5562 - val_loss: 0.8435 - val_accuracy: 0.6116 Epoch 3/30 119/120 [============================>.] - ETA: 0s - loss: 0.8996 - accuracy: 0.5646 Epoch 3: val_accuracy did not improve from 0.61161 120/120 [==============================] - 6s 46ms/step - loss: 0.8993 - accuracy: 0.5646 - val_loss: 0.8510 - val_accuracy: 0.6116 Epoch 4/30 119/120 [============================>.] - ETA: 0s - loss: 0.8719 - accuracy: 0.5843 Epoch 4: val_accuracy did not improve from 0.61161 120/120 [==============================] - 6s 46ms/step - loss: 0.8730 - accuracy: 0.5836 - val_loss: 0.8610 - val_accuracy: 0.5670 Epoch 5/30 120/120 [==============================] - ETA: 0s - loss: 0.8554 - accuracy: 0.5966 Epoch 5: val_accuracy did not improve from 0.61161 120/120 [==============================] - 6s 46ms/step - loss: 0.8554 - accuracy: 0.5966 - val_loss: 0.8345 - val_accuracy: 0.5491 Epoch 6/30 119/120 [============================>.] - ETA: 0s - loss: 0.8313 - accuracy: 0.6056 Epoch 6: val_accuracy did not improve from 0.61161 120/120 [==============================] - 6s 46ms/step - loss: 0.8305 - accuracy: 0.6065 - val_loss: 0.8406 - val_accuracy: 0.5982 Epoch 7/30 119/120 [============================>.] - ETA: 0s - loss: 0.8110 - accuracy: 0.6203 Epoch 7: val_accuracy did not improve from 0.61161 120/120 [==============================] - 6s 46ms/step - loss: 0.8113 - accuracy: 0.6206 - val_loss: 0.8709 - val_accuracy: 0.6027 Epoch 8/30 119/120 [============================>.] - ETA: 0s - loss: 0.7824 - accuracy: 0.6313 Epoch 8: val_accuracy did not improve from 0.61161 120/120 [==============================] - 6s 46ms/step - loss: 0.7818 - accuracy: 0.6318 - val_loss: 0.8546 - val_accuracy: 0.6116 Epoch 9/30 119/120 [============================>.] - ETA: 0s - loss: 0.7649 - accuracy: 0.6486 Epoch 9: val_accuracy improved from 0.61161 to 0.62946, saving model to best_model.h5 120/120 [==============================] - 7s 62ms/step - loss: 0.7636 - accuracy: 0.6495 - val_loss: 0.8046 - val_accuracy: 0.6295 Epoch 10/30 120/120 [==============================] - ETA: 0s - loss: 0.7360 - accuracy: 0.6591 Epoch 10: val_accuracy did not improve from 0.62946 120/120 [==============================] - 6s 47ms/step - loss: 0.7360 - accuracy: 0.6591 - val_loss: 0.8601 - val_accuracy: 0.5714 Epoch 11/30 119/120 [============================>.] - ETA: 0s - loss: 0.7235 - accuracy: 0.6605 Epoch 11: val_accuracy did not improve from 0.62946 120/120 [==============================] - 6s 47ms/step - loss: 0.7237 - accuracy: 0.6602 - val_loss: 0.9096 - val_accuracy: 0.5804 Epoch 12/30 120/120 [==============================] - ETA: 0s - loss: 0.6872 - accuracy: 0.6857 Epoch 12: val_accuracy did not improve from 0.62946 120/120 [==============================] - 6s 47ms/step - loss: 0.6872 - accuracy: 0.6857 - val_loss: 0.8552 - val_accuracy: 0.6250 Epoch 13/30 120/120 [==============================] - ETA: 0s - loss: 0.6454 - accuracy: 0.6995 Epoch 13: val_accuracy improved from 0.62946 to 0.63839, saving model to best_model.h5 120/120 [==============================] - 6s 48ms/step - loss: 0.6454 - accuracy: 0.6995 - val_loss: 0.9689 - val_accuracy: 0.6384 Epoch 14/30 120/120 [==============================] - ETA: 0s - loss: 0.6017 - accuracy: 0.7307 Epoch 14: val_accuracy did not improve from 0.63839 120/120 [==============================] - 6s 47ms/step - loss: 0.6017 - accuracy: 0.7307 - val_loss: 1.1019 - val_accuracy: 0.5759 Epoch 15/30 120/120 [==============================] - ETA: 0s - loss: 0.5800 - accuracy: 0.7490 Epoch 15: val_accuracy did not improve from 0.63839 120/120 [==============================] - 6s 47ms/step - loss: 0.5800 - accuracy: 0.7490 - val_loss: 0.9538 - val_accuracy: 0.5893 Epoch 16/30 120/120 [==============================] - ETA: 0s - loss: 0.5525 - accuracy: 0.7565 Epoch 16: val_accuracy did not improve from 0.63839 120/120 [==============================] - 6s 47ms/step - loss: 0.5525 - accuracy: 0.7565 - val_loss: 1.0494 - val_accuracy: 0.6071 Epoch 17/30 120/120 [==============================] - ETA: 0s - loss: 0.5104 - accuracy: 0.7763 Epoch 17: val_accuracy did not improve from 0.63839 120/120 [==============================] - 6s 48ms/step - loss: 0.5104 - accuracy: 0.7763 - val_loss: 1.0959 - val_accuracy: 0.5938 Epoch 18/30 120/120 [==============================] - ETA: 0s - loss: 0.4799 - accuracy: 0.7893 Epoch 18: val_accuracy did not improve from 0.63839 120/120 [==============================] - 6s 47ms/step - loss: 0.4799 - accuracy: 0.7893 - val_loss: 1.2103 - val_accuracy: 0.6116 Epoch 19/30 120/120 [==============================] - ETA: 0s - loss: 0.4597 - accuracy: 0.7961 Epoch 19: val_accuracy did not improve from 0.63839 120/120 [==============================] - 6s 48ms/step - loss: 0.4597 - accuracy: 0.7961 - val_loss: 1.2058 - val_accuracy: 0.5759 Epoch 20/30 120/120 [==============================] - ETA: 0s - loss: 0.4267 - accuracy: 0.8109 Epoch 20: val_accuracy did not improve from 0.63839 120/120 [==============================] - 6s 47ms/step - loss: 0.4267 - accuracy: 0.8109 - val_loss: 1.3089 - val_accuracy: 0.5848 Epoch 21/30 120/120 [==============================] - ETA: 0s - loss: 0.3868 - accuracy: 0.8294 Epoch 21: val_accuracy did not improve from 0.63839 120/120 [==============================] - 6s 48ms/step - loss: 0.3868 - accuracy: 0.8294 - val_loss: 1.2135 - val_accuracy: 0.6384 Epoch 22/30 120/120 [==============================] - ETA: 0s - loss: 0.3542 - accuracy: 0.8477 Epoch 22: val_accuracy did not improve from 0.63839 120/120 [==============================] - 6s 48ms/step - loss: 0.3542 - accuracy: 0.8477 - val_loss: 1.5080 - val_accuracy: 0.5759 Epoch 23/30 120/120 [==============================] - ETA: 0s - loss: 0.3434 - accuracy: 0.8529 Epoch 23: val_accuracy improved from 0.63839 to 0.65179, saving model to best_model.h5 120/120 [==============================] - 8s 66ms/step - loss: 0.3434 - accuracy: 0.8529 - val_loss: 1.2941 - val_accuracy: 0.6518 Epoch 24/30 119/120 [============================>.] - ETA: 0s - loss: 0.3162 - accuracy: 0.8621 Epoch 24: val_accuracy did not improve from 0.65179 120/120 [==============================] - 6s 48ms/step - loss: 0.3151 - accuracy: 0.8628 - val_loss: 1.4694 - val_accuracy: 0.5893 Epoch 25/30 119/120 [============================>.] - ETA: 0s - loss: 0.3081 - accuracy: 0.8606 Epoch 25: val_accuracy did not improve from 0.65179 120/120 [==============================] - 6s 47ms/step - loss: 0.3086 - accuracy: 0.8604 - val_loss: 1.7652 - val_accuracy: 0.6116 Epoch 26/30 120/120 [==============================] - ETA: 0s - loss: 0.2912 - accuracy: 0.8690 Epoch 26: val_accuracy did not improve from 0.65179 120/120 [==============================] - 6s 48ms/step - loss: 0.2912 - accuracy: 0.8690 - val_loss: 1.5449 - val_accuracy: 0.6027 Epoch 27/30 119/120 [============================>.] - ETA: 0s - loss: 0.2734 - accuracy: 0.8816 Epoch 27: val_accuracy did not improve from 0.65179 120/120 [==============================] - 6s 48ms/step - loss: 0.2732 - accuracy: 0.8815 - val_loss: 1.7292 - val_accuracy: 0.6027 Epoch 28/30 120/120 [==============================] - ETA: 0s - loss: 0.2621 - accuracy: 0.8878 Epoch 28: val_accuracy did not improve from 0.65179 120/120 [==============================] - 6s 48ms/step - loss: 0.2621 - accuracy: 0.8878 - val_loss: 1.5342 - val_accuracy: 0.6161 Epoch 29/30 120/120 [==============================] - ETA: 0s - loss: 0.2390 - accuracy: 0.8948 Epoch 29: val_accuracy did not improve from 0.65179 120/120 [==============================] - 6s 48ms/step - loss: 0.2390 - accuracy: 0.8948 - val_loss: 1.7782 - val_accuracy: 0.5714 Epoch 30/30 119/120 [============================>.] - ETA: 0s - loss: 0.2298 - accuracy: 0.8897 Epoch 30: val_accuracy did not improve from 0.65179 120/120 [==============================] - 6s 48ms/step - loss: 0.2294 - accuracy: 0.8904 - val_loss: 1.8460 - val_accuracy: 0.5580
train_acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
train_loss = history.history['loss']
val_loss = history.history['val_loss']
# Create separate plots for accuracy and loss
plt.figure(figsize=(10, 5))
# Accuracy plot
plt.subplot(121)
plt.plot(train_acc, label='Training Accuracy')
plt.plot(val_acc, label='Validation Accuracy')
plt.title('Model Accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
# Loss plot
plt.subplot(122)
plt.plot(train_loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.title('Model Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.tight_layout()
plt.show()
#for getting just 3000 images from each classes
target_not_phe = info_df_256[info_df_256['class']==0].sample(3000)
target_not_phe_not_op = info_df_256[info_df_256['class']==2].sample(3000)
target_phe =info_df_256[info_df_256['class']==1].sample(3000)
combine_model_df_3k = pd.concat([target_not_phe,target_phe,target_not_phe_not_op],axis=0)
combine_model_df_3k.reset_index(drop=True)
combine_model_df_3k
| patientId | x | y | width | height | Target | class | AGE | SEX | ViewPosition | BodyPart | glcm_contrast | glcm_homogeneity | glcm_energy | glcm_correlation | agecat | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 9027 | 6452c673-1a45-429a-a2ca-df17ca4ec27e | NaN | NaN | NaN | NaN | 0 | 0 | 47 | 1 | PA | CHEST | 321.024737 | 0.179758 | 0.026578 | 0.966599 | old |
| 6028 | 4b912423-ef5e-45c9-90a3-b04fc7977653 | NaN | NaN | NaN | NaN | 0 | 0 | 56 | 1 | PA | CHEST | 248.959226 | 0.165675 | 0.017055 | 0.969842 | old |
| 25541 | e4cd65ae-65de-44fc-a6b2-ebbc46d2e8d8 | NaN | NaN | NaN | NaN | 0 | 0 | 46 | 0 | PA | CHEST | 518.154554 | 0.202925 | 0.024782 | 0.929619 | old |
| 16383 | 9ea1cddd-4382-414d-809a-2364d508c569 | NaN | NaN | NaN | NaN | 0 | 0 | 52 | 0 | PA | CHEST | 310.744266 | 0.205751 | 0.023469 | 0.969094 | old |
| 12200 | 7cf7f5f9-ee16-49a1-86ea-ec7c7e2b9956 | NaN | NaN | NaN | NaN | 0 | 0 | 49 | 1 | PA | CHEST | 453.555534 | 0.169285 | 0.016910 | 0.949616 | old |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 28283 | fa6f2444-e397-47d7-aa38-60302c4b454b | NaN | NaN | NaN | NaN | 0 | 2 | 49 | 1 | PA | CHEST | 277.707292 | 0.172032 | 0.020459 | 0.968026 | old |
| 22167 | c8a6b62b-8f1e-4b58-9df1-0892a4910bcd | NaN | NaN | NaN | NaN | 0 | 2 | 52 | 1 | PA | CHEST | 244.810896 | 0.199665 | 0.029163 | 0.972565 | old |
| 11651 | 789e0f7e-a921-4957-a784-e4766b77a99b | NaN | NaN | NaN | NaN | 0 | 2 | 61 | 0 | PA | CHEST | 67.679147 | 0.294047 | 0.034462 | 0.973103 | vold |
| 22742 | cd378513-15c9-4d85-a7f5-57ed6a36bbd4 | NaN | NaN | NaN | NaN | 0 | 2 | 69 | 1 | AP | CHEST | 72.506128 | 0.241748 | 0.023241 | 0.977788 | vold |
| 5868 | 4a4510a3-0439-414b-adf8-9d5a09fb61ab | NaN | NaN | NaN | NaN | 0 | 2 | 24 | 0 | PA | CHEST | 242.834958 | 0.200072 | 0.024904 | 0.952339 | Young |
9000 rows × 16 columns
combine_model_df_3k['class'] = combine_model_df_3k['class'].astype(str)
combine_model_df_3k['patientId'] = combine_model_df_3k['patientId'] + '.jpg'
# Split the dataset into training and validation sets
train_df3, val_df3 = train_test_split(combine_model_df_3k, test_size=0.2, random_state=77)
epocs_count = 30
datagen = ImageDataGenerator(rescale=1./255, validation_split=0.2)
train_generator = datagen.flow_from_dataframe(
dataframe=train_df3,
directory=image_directory,
x_col="patientId", # Use the column name for file paths
y_col="class", # Use the column name for labels
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode='categorical',
subset='training'
)
validation_generator = datagen.flow_from_dataframe(
dataframe=val_df3,
directory=image_directory,
x_col="patientId", # Use the column name for file paths
y_col="class", # Use the column name for labels
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode='categorical',
subset='validation'
)
model_cnn256_3k = Sequential()
model_cnn256_3k.add(Conv2D(9,(3,3),activation='relu',input_shape = (img_width,img_height,1)))
model_cnn256_3k.add(MaxPooling2D((2,2)))
model_cnn256_3k.add(Conv2D(16,(3,3),activation='relu'))
model_cnn256_3k.add(MaxPooling2D((2,2)))
model_cnn256_3k.add(Conv2D(32,(3,3),activation='relu'))
model_cnn256_3k.add(MaxPooling2D((2,2)))
model_cnn256_3k.add(Flatten())
model_cnn256_3k.add(Dense(64,activation='relu'))
model_cnn256_3k.add(Dropout(0.5))
model_cnn256_3k.add(Dense(32,activation='relu'))
model_cnn256_3k.add(Dense(3,activation='softmax'))
# Compile the model_cnn256_3k
model_cnn256_3k.compile(optimizer='adam',
loss='categorical_crossentropy', # Use categorical cross-entropy for multi-class classification
metrics=['accuracy'],)
# Define callbacks
checkpoint = ModelCheckpoint("best_model.h5", monitor='val_accuracy', verbose=1, save_best_only=True, mode='max')
early_stopping = EarlyStopping(monitor='val_accuracy', patience=15, verbose=1, restore_best_weights=True)
# Train the model
history = model_cnn256_3k.fit(
train_generator,
steps_per_epoch=train_generator.samples // batch_size,
epochs=epocs_count,
validation_data=validation_generator,
validation_steps=validation_generator.samples // batch_size,
callbacks=[checkpoint, early_stopping]
)
Found 5760 validated image filenames belonging to 3 classes. Found 360 validated image filenames belonging to 3 classes. Epoch 1/30 180/180 [==============================] - ETA: 0s - loss: 0.9765 - accuracy: 0.5099 Epoch 1: val_accuracy improved from -inf to 0.60227, saving model to best_model.h5 180/180 [==============================] - 76s 420ms/step - loss: 0.9765 - accuracy: 0.5099 - val_loss: 0.8745 - val_accuracy: 0.6023 Epoch 2/30 180/180 [==============================] - ETA: 0s - loss: 0.8905 - accuracy: 0.5698 Epoch 2: val_accuracy improved from 0.60227 to 0.61932, saving model to best_model.h5 180/180 [==============================] - 9s 48ms/step - loss: 0.8905 - accuracy: 0.5698 - val_loss: 0.8238 - val_accuracy: 0.6193 Epoch 3/30 180/180 [==============================] - ETA: 0s - loss: 0.8641 - accuracy: 0.5903 Epoch 3: val_accuracy did not improve from 0.61932 180/180 [==============================] - 9s 47ms/step - loss: 0.8641 - accuracy: 0.5903 - val_loss: 0.8533 - val_accuracy: 0.6080 Epoch 4/30 180/180 [==============================] - ETA: 0s - loss: 0.8392 - accuracy: 0.6030 Epoch 4: val_accuracy improved from 0.61932 to 0.63068, saving model to best_model.h5 180/180 [==============================] - 9s 48ms/step - loss: 0.8392 - accuracy: 0.6030 - val_loss: 0.7967 - val_accuracy: 0.6307 Epoch 5/30 179/180 [============================>.] - ETA: 0s - loss: 0.8136 - accuracy: 0.6170 Epoch 5: val_accuracy did not improve from 0.63068 180/180 [==============================] - 9s 48ms/step - loss: 0.8132 - accuracy: 0.6175 - val_loss: 0.8457 - val_accuracy: 0.6165 Epoch 6/30 179/180 [============================>.] - ETA: 0s - loss: 0.7709 - accuracy: 0.6414 Epoch 6: val_accuracy did not improve from 0.63068 180/180 [==============================] - 9s 48ms/step - loss: 0.7722 - accuracy: 0.6410 - val_loss: 0.8109 - val_accuracy: 0.6193 Epoch 7/30 180/180 [==============================] - ETA: 0s - loss: 0.7419 - accuracy: 0.6601 Epoch 7: val_accuracy improved from 0.63068 to 0.63352, saving model to best_model.h5 180/180 [==============================] - 9s 48ms/step - loss: 0.7419 - accuracy: 0.6601 - val_loss: 0.8246 - val_accuracy: 0.6335 Epoch 8/30 179/180 [============================>.] - ETA: 0s - loss: 0.6833 - accuracy: 0.6849 Epoch 8: val_accuracy did not improve from 0.63352 180/180 [==============================] - 9s 48ms/step - loss: 0.6841 - accuracy: 0.6835 - val_loss: 0.8885 - val_accuracy: 0.6108 Epoch 9/30 180/180 [==============================] - ETA: 0s - loss: 0.6506 - accuracy: 0.7016 Epoch 9: val_accuracy improved from 0.63352 to 0.64489, saving model to best_model.h5 180/180 [==============================] - 9s 49ms/step - loss: 0.6506 - accuracy: 0.7016 - val_loss: 0.8711 - val_accuracy: 0.6449 Epoch 10/30 179/180 [============================>.] - ETA: 0s - loss: 0.6104 - accuracy: 0.7259 Epoch 10: val_accuracy did not improve from 0.64489 180/180 [==============================] - 9s 48ms/step - loss: 0.6102 - accuracy: 0.7262 - val_loss: 0.8734 - val_accuracy: 0.6335 Epoch 11/30 180/180 [==============================] - ETA: 0s - loss: 0.5571 - accuracy: 0.7405 Epoch 11: val_accuracy did not improve from 0.64489 180/180 [==============================] - 9s 48ms/step - loss: 0.5571 - accuracy: 0.7405 - val_loss: 0.9926 - val_accuracy: 0.5795 Epoch 12/30 179/180 [============================>.] - ETA: 0s - loss: 0.5232 - accuracy: 0.7664 Epoch 12: val_accuracy did not improve from 0.64489 180/180 [==============================] - 9s 49ms/step - loss: 0.5229 - accuracy: 0.7663 - val_loss: 1.0769 - val_accuracy: 0.5994 Epoch 13/30 180/180 [==============================] - ETA: 0s - loss: 0.4760 - accuracy: 0.7882 Epoch 13: val_accuracy did not improve from 0.64489 180/180 [==============================] - 9s 49ms/step - loss: 0.4760 - accuracy: 0.7882 - val_loss: 1.1752 - val_accuracy: 0.6278 Epoch 14/30 179/180 [============================>.] - ETA: 0s - loss: 0.4360 - accuracy: 0.8008 Epoch 14: val_accuracy did not improve from 0.64489 180/180 [==============================] - 9s 49ms/step - loss: 0.4370 - accuracy: 0.8003 - val_loss: 1.1446 - val_accuracy: 0.6420 Epoch 15/30 180/180 [==============================] - ETA: 0s - loss: 0.4087 - accuracy: 0.8151 Epoch 15: val_accuracy did not improve from 0.64489 180/180 [==============================] - 9s 48ms/step - loss: 0.4087 - accuracy: 0.8151 - val_loss: 1.1687 - val_accuracy: 0.6051 Epoch 16/30 179/180 [============================>.] - ETA: 0s - loss: 0.3467 - accuracy: 0.8441 Epoch 16: val_accuracy did not improve from 0.64489 180/180 [==============================] - 9s 49ms/step - loss: 0.3473 - accuracy: 0.8441 - val_loss: 1.2720 - val_accuracy: 0.6250 Epoch 17/30 180/180 [==============================] - ETA: 0s - loss: 0.3378 - accuracy: 0.8528 Epoch 17: val_accuracy did not improve from 0.64489 180/180 [==============================] - 9s 49ms/step - loss: 0.3378 - accuracy: 0.8528 - val_loss: 1.3732 - val_accuracy: 0.6278 Epoch 18/30 180/180 [==============================] - ETA: 0s - loss: 0.3212 - accuracy: 0.8545 Epoch 18: val_accuracy did not improve from 0.64489 180/180 [==============================] - 9s 49ms/step - loss: 0.3212 - accuracy: 0.8545 - val_loss: 1.5181 - val_accuracy: 0.6278 Epoch 19/30 180/180 [==============================] - ETA: 0s - loss: 0.2872 - accuracy: 0.8724 Epoch 19: val_accuracy did not improve from 0.64489 180/180 [==============================] - 9s 49ms/step - loss: 0.2872 - accuracy: 0.8724 - val_loss: 1.6925 - val_accuracy: 0.6108 Epoch 20/30 179/180 [============================>.] - ETA: 0s - loss: 0.2789 - accuracy: 0.8757 Epoch 20: val_accuracy did not improve from 0.64489 180/180 [==============================] - 9s 49ms/step - loss: 0.2796 - accuracy: 0.8755 - val_loss: 1.6426 - val_accuracy: 0.5966 Epoch 21/30 179/180 [============================>.] - ETA: 0s - loss: 0.2604 - accuracy: 0.8874 Epoch 21: val_accuracy did not improve from 0.64489 180/180 [==============================] - 9s 52ms/step - loss: 0.2598 - accuracy: 0.8877 - val_loss: 1.8611 - val_accuracy: 0.5909 Epoch 22/30 179/180 [============================>.] - ETA: 0s - loss: 0.2580 - accuracy: 0.8890 Epoch 22: val_accuracy did not improve from 0.64489 180/180 [==============================] - 9s 51ms/step - loss: 0.2588 - accuracy: 0.8887 - val_loss: 1.7013 - val_accuracy: 0.6051 Epoch 23/30 180/180 [==============================] - ETA: 0s - loss: 0.2327 - accuracy: 0.8936 Epoch 23: val_accuracy did not improve from 0.64489 180/180 [==============================] - 9s 50ms/step - loss: 0.2327 - accuracy: 0.8936 - val_loss: 1.8726 - val_accuracy: 0.6136 Epoch 24/30 179/180 [============================>.] - ETA: 0s - loss: 0.2353 - accuracy: 0.9000 Epoch 24: val_accuracy did not improve from 0.64489 Restoring model weights from the end of the best epoch: 9. 180/180 [==============================] - 9s 50ms/step - loss: 0.2356 - accuracy: 0.9000 - val_loss: 1.9427 - val_accuracy: 0.5795 Epoch 24: early stopping
train_acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
train_loss = history.history['loss']
val_loss = history.history['val_loss']
# Create separate plots for accuracy and loss
plt.figure(figsize=(10, 5))
# Accuracy plot
plt.subplot(121)
plt.plot(train_acc, label='Training Accuracy')
plt.plot(val_acc, label='Validation Accuracy')
plt.title('Model Accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
# Loss plot
plt.subplot(122)
plt.plot(train_loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.title('Model Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.tight_layout()
plt.show()
from sklearn.metrics import confusion_matrix, classification_report
from sklearn.metrics import precision_score, recall_score, f1_score
# Evaluate the model_cnn256_3k on the validation dataset
val_loss, val_accuracy = model_cnn256_3k.evaluate(validation_generator, steps=12)
# Predict probabilities for the validation set
val_predictions = model_cnn256_3k.predict(validation_generator, steps=12)
# Convert probabilities to class labels
val_pred_labels = np.argmax(val_predictions, axis=1)
val_true_labels = validation_generator.classes
# Calculate precision, recall, and F1 score manually
precision = precision_score(val_true_labels, val_pred_labels, average='weighted')
recall = recall_score(val_true_labels, val_pred_labels, average='weighted')
f1 = f1_score(val_true_labels, val_pred_labels, average='weighted')
print("Validation Accuracy:", val_accuracy)
print("Precision:", precision)
print("Recall:", recall)
print("F1 Score:", f1)
# Calculate confusion matrix
cm = confusion_matrix(val_true_labels, val_pred_labels)
# Class mapping provided
#class_mapping = val_generator.class_indices
class_mapping = {'Lung Opacity': 0, 'No Lung Opacity / Not Normal': 1, 'Normal': 2}
# Plot confusion matrix with numerical values and categorical labels
plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', cbar=False,
xticklabels=class_mapping.keys(), yticklabels=class_mapping.keys())
plt.title('Confusion Matrix')
plt.xlabel('Predicted Labels')
plt.ylabel('True Labels')
plt.show()
12/12 [==============================] - 1s 55ms/step - loss: 0.8688 - accuracy: 0.6500 Validation Accuracy: 0.6499999761581421 Precision: 0.32223111708750435 Recall: 0.32222222222222224 F1 Score: 0.3220422408842951
For more we can do transfer learning with existing models like resnet , vgg , yolo , mobile net for batter accuracy and identification through deep learning .
info_df_128 = pd.read_csv('infodf.csv')
size = 128
info_df_128['x'] = info_df_128['x'].apply(calculatetheimageboundings)
info_df_128['y'] = info_df_128['y'].apply(calculatetheimageboundings)
info_df_128['width'] = info_df_128['width'].apply(calculatetheimageboundings)
info_df_128['height'] = info_df_128['height'].apply(calculatetheimageboundings)
info_df_128
| Unnamed: 0 | patientId | x | y | width | height | Target | class | AGE | SEX | ViewPosition | BodyPart | glcm_contrast | glcm_homogeneity | glcm_energy | glcm_correlation | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 0004cfab-14fd-4e49-80ba-63a80b6bddd6 | NaN | NaN | NaN | NaN | 0 | 2 | 51 | 0 | PA | CHEST | 240.363107 | 0.221791 | 0.041201 | 0.977566 |
| 1 | 1 | 00313ee0-9eaa-42f4-b0ab-c148ed3241cd | NaN | NaN | NaN | NaN | 0 | 2 | 48 | 0 | PA | CHEST | 52.810114 | 0.333943 | 0.077472 | 0.983760 |
| 2 | 2 | 00322d4d-1c29-4943-afc9-b6754be640eb | NaN | NaN | NaN | NaN | 0 | 2 | 19 | 1 | AP | CHEST | 220.881035 | 0.200721 | 0.025836 | 0.968193 |
| 3 | 3 | 003d8fa0-6bf1-40ed-b54c-ac657f8495c5 | NaN | NaN | NaN | NaN | 0 | 0 | 28 | 1 | PA | CHEST | 406.426794 | 0.165048 | 0.019650 | 0.954598 |
| 4 | 4 | 00436515-870c-4b36-a041-de91049b9ab4 | 33.0 | 19.0 | 26.0 | 47.0 | 1 | 1 | 32 | 0 | AP | CHEST | 86.499986 | 0.236534 | 0.020687 | 0.986255 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 30222 | 37621 | c1ec14ff-f6d7-4b38-b0cb-fe07041cbdc8 | 23.0 | 37.0 | 28.0 | 47.0 | 1 | 1 | 54 | 1 | AP | CHEST | 251.202459 | 0.243280 | 0.057668 | 0.932018 |
| 30223 | 37623 | c1edf42b-5958-47ff-a1e7-4f23d99583ba | NaN | NaN | NaN | NaN | 0 | 0 | 46 | 0 | PA | CHEST | 139.894010 | 0.238966 | 0.074233 | 0.985241 |
| 30224 | 37624 | c1f6b555-2eb1-4231-98f6-50a963976431 | NaN | NaN | NaN | NaN | 0 | 0 | 45 | 1 | PA | CHEST | 325.506092 | 0.212639 | 0.023197 | 0.924871 |
| 30225 | 37625 | c1f7889a-9ea9-4acb-b64c-b737c929599a | 71.0 | 49.0 | 32.0 | 43.0 | 1 | 1 | 72 | 0 | AP | CHEST | 198.700831 | 0.227273 | 0.023604 | 0.973146 |
| 30226 | 37627 | c1f7889a-9ea9-4acb-b64c-b737c929599a | 29.0 | 53.0 | 25.0 | 44.0 | 1 | 1 | 72 | 0 | AP | CHEST | 198.700831 | 0.227273 | 0.023604 | 0.973146 |
30227 rows × 16 columns
# Define image dimensions and batch size
img_width, img_height = 128, 128
batch_size = 32
# Define the directory where the images are stored
image_directory = 'train_images/images_128_jpg'
#for getting just 1000 images from each classes
target_not_phe_100 = info_df_128[info_df_128['class']==0].sample(500)
target_phe_100 =info_df_128[info_df_128['class']==1].sample(500)
target_not_phe_not_op_100 = info_df_128[info_df_128['class']==2].sample(500)
combine_model_df_100 = pd.concat([target_not_phe_100,target_phe_100,target_not_phe_not_op_100],axis=0)
combine_model_df_100.reset_index(drop=True)
# combine_model_df_100
Df_make_100 = combine_model_df_100[['patientId','class']].copy()
Df_make_100['patientId'] = Df_make_100['patientId'] +'.jpg'
Df_make_100['class'] = Df_make_100['class'].astype('str')
Df_make_100.info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 1500 entries, 845 to 11428 Data columns (total 2 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 patientId 1500 non-null object 1 class 1500 non-null object dtypes: object(2) memory usage: 35.2+ KB
import tensorflow as tf
train_df_100, val_df_100= train_test_split(Df_make_100, test_size=0.2, random_state=5)
epocs_count = 30
datagen = ImageDataGenerator(rescale=1./255)
datagen2 = ImageDataGenerator(rescale=1./255)
train_generator1 = datagen.flow_from_dataframe(
dataframe=train_df_100,
directory=image_directory,
x_col="patientId", # Use the column name for file paths
y_col="class", # Use the column name for labels
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode='sparse',
# subset='training',
# shuffle = True,
# seed=7
)
validation_generator1 = datagen2.flow_from_dataframe(
dataframe=val_df_100,
directory=image_directory,
x_col="patientId", # Use the column name for file paths
y_col="class", # Use the column name for labels
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode='sparse',
# subset='validation',
# shuffle=True,
# seed=7
)
Found 1200 validated image filenames belonging to 3 classes. Found 300 validated image filenames belonging to 3 classes.
x_train=np.concatenate([train_generator1.next()[0] for i in range(train_generator1.__len__())])
y_train=np.concatenate([train_generator1.next()[1] for i in range(train_generator1.__len__())])
print(x_train.shape)
print(y_train.shape)
(1200, 128, 128, 3) (1200,)
x_val=np.concatenate([validation_generator1.next()[0] for i in range(validation_generator1.__len__())])
y_val=np.concatenate([validation_generator1.next()[1] for i in range(validation_generator1.__len__())])
print(x_val.shape)
print(y_val.shape)
(300, 128, 128, 3) (300,)
datastore_1000 = [x_train,y_train,x_val,y_val]
np.save('datastorePne_1000.npy',np.array(datastore_1000,dtype='object'),allow_pickle=True)
x_train,y_train,x_val,y_val = np.load('datastorePne_1000.npy',allow_pickle=True)
print(x_train.shape,y_train.shape,x_val.shape,y_val.shape)
(1200, 128, 128, 3) (1200,) (300, 128, 128, 3) (300,)
import random
def make_pairs(x, y):
"""Creates a tuple containing image pairs with corresponding label.
Arguments:
x: List containing images, each index in this list corresponds to one image.
y: List containing labels, each label with datatype of `int`.
Returns:
Tuple containing two numpy arrays as (pairs_of_samples, labels),
where pairs_of_samples' shape is (2len(x), 2,n_features_dims) and
labels are a binary array of shape (2len(x)).
"""
num_classes = max(y) + 1
digit_indices = [np.where(y == i)[0] for i in range(num_classes)]
pairs = []
labels = []
for idx1 in range(len(x)):
# add a matching example
x1 = x[idx1]
label1 = y[idx1]
idx2 = random.choice(digit_indices[label1])
x2 = x[idx2]
pairs += [[x1, x2]]
labels += [1]
# add a non-matching example
label2 = random.randint(0, num_classes - 1)
while label2 == label1:
label2 = random.randint(0, num_classes - 1)
idx2 = random.choice(digit_indices[label2])
x2 = x[idx2]
pairs += [[x1, x2]]
labels += [0]
return np.array(pairs), np.array(labels).astype("float32")
# Initialize input values such as margin, input image size(height, width), epochs, batch_size and output classes for this example
epochs = 100
batch_size = 8
margin = 1
output_classes =3
img_height = 128
img_width = 128
print(x_train.dtype)
print(x_val.dtype)
float32 float32
train_wholelabel = y_train.astype("uint8")
val_wholelabel = y_val.astype("uint8")
print(f'{train_wholelabel.dtype},{val_wholelabel.dtype}')
uint8,uint8
pairs_train, labels_train = make_pairs(x_train, train_wholelabel)
pairs_val, labels_val = make_pairs(x_val, val_wholelabel)
print(pairs_train.shape)
print(pairs_val.shape)
print(labels_train.shape)
(2400, 2, 128, 128, 3) (600, 2, 128, 128, 3) (2400,)
x_train_1 = pairs_train[:, 0]
x_train_2 = pairs_train[:, 1]
print(x_train_1.shape)
print(x_train_2.shape)
(2400, 128, 128, 3) (2400, 128, 128, 3)
x_val_1 = pairs_val[:, 0]
x_val_2 = pairs_val[:, 1]
print(x_val_1.shape)
print(x_val_2.shape)
(600, 128, 128, 3) (600, 128, 128, 3)
IMG_SHAPE = x_train_1.shape[1:]
IMG_SHAPE
(128, 128, 3)
# Measuring distance between two vectors(images)
def euclidean_distance(vects):
"""Find the Euclidean distance between two vectors.
Arguments:
vects: List containing two tensors of same length.
Returns:
Tensor containing euclidean distance
(as floating point value) between vectors.
"""
x, y = vects
sum_square = tf.math.reduce_sum(tf.math.square(x - y), axis=1, keepdims=True)
return tf.math.sqrt(tf.math.maximum(sum_square, tf.keras.backend.epsilon()))
# Defining the Model
inputx = tf.keras.Input(shape=IMG_SHAPE)
x = tf.keras.layers.BatchNormalization()(inputx)
x = tf.keras.layers.Conv2D(4, (5, 5), activation="tanh")(x)
x = tf.keras.layers.AveragePooling2D(pool_size=(2, 2))(x)
x = tf.keras.layers.Conv2D(16, (5, 5), activation="tanh")(x)
x = tf.keras.layers.AveragePooling2D(pool_size=(2, 2))(x)
x = tf.keras.layers.Flatten()(x)
x = tf.keras.layers.BatchNormalization()(x)
x = tf.keras.layers.Dense(output_classes, activation="tanh")(x)
embedding_network = tf.keras.Model(inputx, x)
input_1 = tf.keras.layers.Input(IMG_SHAPE)
input_2 = tf.keras.layers.Input(IMG_SHAPE)
""" As mentioned above, Siamese Network share weights between tower networks (sister networks).
To allow this, we will use same embedding network for both tower networks. """
tower_1 = embedding_network(input_1)
tower_2 = embedding_network(input_2)
merge_layer = tf.keras.layers.Lambda(euclidean_distance)([tower_1, tower_2])
normal_layer = tf.keras.layers.BatchNormalization()(merge_layer)
output_layer = tf.keras.layers.Dense(1, activation="sigmoid")(normal_layer)
siamese = tf.keras.Model(inputs=[input_1, input_2], outputs=output_layer)
# Loss Function
def loss(margin=1):
"""Provides 'contrastive_loss' an enclosing scope with variable 'margin'.
Arguments:
margin: Integer, defines the baseline for distance for which pairs
should be classified as dissimilar. - (default is 1).
Returns:
'contrastive_loss' function with data ('margin') attached.
"""
# Contrastive loss = mean( (1-true_value) * square(prediction) +
# true_value * square( max(margin-prediction, 0) ))
def contrastive_loss(y_true, y_pred):
"""Calculates the contrastive loss.
Arguments:
y_true: List of labels, each label is of type float32.
y_pred: List of predictions of same length as of y_true,
each label is of type float32.
Returns:
A tensor containing contrastive loss as floating point value.
"""
square_pred = tf.math.square(y_pred)
margin_square = tf.math.square(tf.math.maximum(margin - (y_pred), 0))
return tf.math.reduce_mean(
(1 - y_true) * square_pred + (y_true) * margin_square
)
return contrastive_loss
siamese.compile(loss=loss(margin=margin), optimizer="RMSprop", metrics=["accuracy"])
siamese.summary()
Model: "model_1"
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_2 (InputLayer) [(None, 128, 128, 3 0 []
)]
input_3 (InputLayer) [(None, 128, 128, 3 0 []
)]
model (Functional) (None, 3) 96127 ['input_2[0][0]',
'input_3[0][0]']
lambda (Lambda) (None, 1) 0 ['model[0][0]',
'model[1][0]']
batch_normalization_2 (BatchNo (None, 1) 4 ['lambda[0][0]']
rmalization)
dense_10 (Dense) (None, 1) 2 ['batch_normalization_2[0][0]']
==================================================================================================
Total params: 96,133
Trainable params: 69,213
Non-trainable params: 26,920
__________________________________________________________________________________________________
history_siamese = siamese.fit(
[x_train_1, x_train_2],
labels_train,
validation_data=([x_val_1, x_val_2], labels_val),
batch_size=batch_size,
epochs=epochs,
)
Epoch 1/100 300/300 [==============================] - 5s 14ms/step - loss: 0.2954 - accuracy: 0.5017 - val_loss: 0.2845 - val_accuracy: 0.5033 Epoch 2/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2706 - accuracy: 0.5017 - val_loss: 0.2719 - val_accuracy: 0.4850 Epoch 3/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2597 - accuracy: 0.5004 - val_loss: 0.2570 - val_accuracy: 0.4883 Epoch 4/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2539 - accuracy: 0.4992 - val_loss: 0.2536 - val_accuracy: 0.4917 Epoch 5/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2523 - accuracy: 0.4954 - val_loss: 0.2521 - val_accuracy: 0.4967 Epoch 6/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2519 - accuracy: 0.4879 - val_loss: 0.2505 - val_accuracy: 0.4933 Epoch 7/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2503 - accuracy: 0.5004 - val_loss: 0.2511 - val_accuracy: 0.4883 Epoch 8/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2506 - accuracy: 0.4913 - val_loss: 0.2502 - val_accuracy: 0.4800 Epoch 9/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2504 - accuracy: 0.5042 - val_loss: 0.2502 - val_accuracy: 0.4900 Epoch 10/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2502 - accuracy: 0.5004 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 11/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2501 - accuracy: 0.4963 - val_loss: 0.2497 - val_accuracy: 0.5067 Epoch 12/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2501 - accuracy: 0.5008 - val_loss: 0.2500 - val_accuracy: 0.5050 Epoch 13/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2500 - accuracy: 0.5042 - val_loss: 0.2496 - val_accuracy: 0.4867 Epoch 14/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2501 - accuracy: 0.4988 - val_loss: 0.2498 - val_accuracy: 0.5133 Epoch 15/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2501 - accuracy: 0.4963 - val_loss: 0.2502 - val_accuracy: 0.4900 Epoch 16/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2501 - accuracy: 0.5058 - val_loss: 0.2498 - val_accuracy: 0.5300 Epoch 17/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2500 - accuracy: 0.5050 - val_loss: 0.2500 - val_accuracy: 0.5150 Epoch 18/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2500 - accuracy: 0.5021 - val_loss: 0.2499 - val_accuracy: 0.4850 Epoch 19/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2500 - accuracy: 0.5017 - val_loss: 0.2500 - val_accuracy: 0.4950 Epoch 20/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2500 - accuracy: 0.5013 - val_loss: 0.2497 - val_accuracy: 0.5450 Epoch 21/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.5096 - val_loss: 0.2498 - val_accuracy: 0.5150 Epoch 22/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2501 - accuracy: 0.4975 - val_loss: 0.2498 - val_accuracy: 0.5317 Epoch 23/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2501 - accuracy: 0.4958 - val_loss: 0.2498 - val_accuracy: 0.5067 Epoch 24/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2500 - accuracy: 0.4900 - val_loss: 0.2498 - val_accuracy: 0.5267 Epoch 25/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2501 - accuracy: 0.4892 - val_loss: 0.2497 - val_accuracy: 0.5217 Epoch 26/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2501 - accuracy: 0.4979 - val_loss: 0.2501 - val_accuracy: 0.4983 Epoch 27/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2501 - accuracy: 0.4933 - val_loss: 0.2499 - val_accuracy: 0.5517 Epoch 28/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2501 - accuracy: 0.4883 - val_loss: 0.2499 - val_accuracy: 0.5350 Epoch 29/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2501 - accuracy: 0.4938 - val_loss: 0.2499 - val_accuracy: 0.5317 Epoch 30/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2501 - accuracy: 0.5008 - val_loss: 0.2499 - val_accuracy: 0.5367 Epoch 31/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.4967 - val_loss: 0.2498 - val_accuracy: 0.5133 Epoch 32/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2499 - accuracy: 0.5113 - val_loss: 0.2499 - val_accuracy: 0.5250 Epoch 33/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2501 - accuracy: 0.4954 - val_loss: 0.2499 - val_accuracy: 0.5033 Epoch 34/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2501 - accuracy: 0.4929 - val_loss: 0.2499 - val_accuracy: 0.5033 Epoch 35/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2501 - accuracy: 0.4925 - val_loss: 0.2499 - val_accuracy: 0.5100 Epoch 36/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2501 - accuracy: 0.4908 - val_loss: 0.2499 - val_accuracy: 0.5167 Epoch 37/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.4938 - val_loss: 0.2500 - val_accuracy: 0.5083 Epoch 38/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2501 - accuracy: 0.4929 - val_loss: 0.2500 - val_accuracy: 0.5050 Epoch 39/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2501 - accuracy: 0.4908 - val_loss: 0.2499 - val_accuracy: 0.5017 Epoch 40/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.5038 - val_loss: 0.2499 - val_accuracy: 0.5083 Epoch 41/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2501 - accuracy: 0.4963 - val_loss: 0.2499 - val_accuracy: 0.5000 Epoch 42/100 300/300 [==============================] - 4s 15ms/step - loss: 0.2501 - accuracy: 0.4829 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 43/100 300/300 [==============================] - 4s 14ms/step - loss: 0.2501 - accuracy: 0.4800 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 44/100 300/300 [==============================] - 4s 14ms/step - loss: 0.2501 - accuracy: 0.4817 - val_loss: 0.2500 - val_accuracy: 0.5233 Epoch 45/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2501 - accuracy: 0.4792 - val_loss: 0.2500 - val_accuracy: 0.5333 Epoch 46/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.4875 - val_loss: 0.2499 - val_accuracy: 0.5117 Epoch 47/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2501 - accuracy: 0.4975 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 48/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.4858 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 49/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2501 - accuracy: 0.4950 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 50/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.4946 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 51/100 300/300 [==============================] - 4s 14ms/step - loss: 0.2500 - accuracy: 0.4954 - val_loss: 0.2500 - val_accuracy: 0.5033 Epoch 52/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.4942 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 53/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.4992 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 54/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.4929 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 55/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.4812 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 56/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.4888 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 57/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.4992 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 58/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.4996 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 59/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.4917 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 60/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2500 - accuracy: 0.4925 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 61/100 300/300 [==============================] - 4s 12ms/step - loss: 0.2500 - accuracy: 0.4946 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 62/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.4883 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 63/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.4967 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 64/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.4858 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 65/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.5000 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 66/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.5000 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 67/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.4950 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 68/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.4904 - val_loss: 0.2500 - val_accuracy: 0.5050 Epoch 69/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.4992 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 70/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.4963 - val_loss: 0.2500 - val_accuracy: 0.4967 Epoch 71/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.5038 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 72/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.4900 - val_loss: 0.2500 - val_accuracy: 0.5200 Epoch 73/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2499 - accuracy: 0.5133 - val_loss: 0.2500 - val_accuracy: 0.5250 Epoch 74/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.5079 - val_loss: 0.2500 - val_accuracy: 0.5433 Epoch 75/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.5104 - val_loss: 0.2498 - val_accuracy: 0.5367 Epoch 76/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.5063 - val_loss: 0.2499 - val_accuracy: 0.5250 Epoch 77/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2499 - accuracy: 0.5088 - val_loss: 0.2499 - val_accuracy: 0.4900 Epoch 78/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.5063 - val_loss: 0.2499 - val_accuracy: 0.5167 Epoch 79/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.5067 - val_loss: 0.2499 - val_accuracy: 0.5067 Epoch 80/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2499 - accuracy: 0.5083 - val_loss: 0.2495 - val_accuracy: 0.5367 Epoch 81/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2502 - accuracy: 0.5008 - val_loss: 0.2494 - val_accuracy: 0.5383 Epoch 82/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2502 - accuracy: 0.4917 - val_loss: 0.2495 - val_accuracy: 0.5167 Epoch 83/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2501 - accuracy: 0.5025 - val_loss: 0.2496 - val_accuracy: 0.5450 Epoch 84/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.5004 - val_loss: 0.2500 - val_accuracy: 0.5217 Epoch 85/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2502 - accuracy: 0.4783 - val_loss: 0.2499 - val_accuracy: 0.5217 Epoch 86/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2501 - accuracy: 0.4913 - val_loss: 0.2499 - val_accuracy: 0.5000 Epoch 87/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2501 - accuracy: 0.4963 - val_loss: 0.2499 - val_accuracy: 0.5300 Epoch 88/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2501 - accuracy: 0.4942 - val_loss: 0.2497 - val_accuracy: 0.5483 Epoch 89/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.5071 - val_loss: 0.2498 - val_accuracy: 0.5267 Epoch 90/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.5004 - val_loss: 0.2497 - val_accuracy: 0.5433 Epoch 91/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.5025 - val_loss: 0.2498 - val_accuracy: 0.5267 Epoch 92/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.5108 - val_loss: 0.2497 - val_accuracy: 0.5433 Epoch 93/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2501 - accuracy: 0.4963 - val_loss: 0.2496 - val_accuracy: 0.5400 Epoch 94/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2501 - accuracy: 0.4896 - val_loss: 0.2497 - val_accuracy: 0.5250 Epoch 95/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.5092 - val_loss: 0.2500 - val_accuracy: 0.5000 Epoch 96/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2501 - accuracy: 0.4867 - val_loss: 0.2502 - val_accuracy: 0.5133 Epoch 97/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.5017 - val_loss: 0.2500 - val_accuracy: 0.4850 Epoch 98/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2499 - accuracy: 0.5042 - val_loss: 0.2496 - val_accuracy: 0.5167 Epoch 99/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2500 - accuracy: 0.5063 - val_loss: 0.2494 - val_accuracy: 0.5700 Epoch 100/100 300/300 [==============================] - 4s 13ms/step - loss: 0.2499 - accuracy: 0.5100 - val_loss: 0.2496 - val_accuracy: 0.5133
def plt_metric(history, metric, title, has_valid=True):
"""Plots the given 'metric' from 'history'.
Arguments:
history: history attribute of History object returned from Model.fit.
metric: Metric to plot, a string value present as key in 'history'.
title: A string to be used as title of plot.
has_valid: Boolean, true if valid data was passed to Model.fit else false.
Returns:
None.
"""
plt.plot(history[metric])
if has_valid:
plt.plot(history["val_" + metric])
plt.legend(["train", "validation"], loc="upper left")
plt.title(title)
plt.ylabel(metric)
plt.xlabel("epoch")
plt.show()
# Plot the accuracy
plt_metric(history=history_siamese.history, metric="accuracy", title="Model accuracy")
# Plot the contrastive loss
plt_metric(history=history_siamese.history, metric="loss", title="Contrastive Loss")
results = siamese.evaluate([x_val_1, x_val_2], labels_val) #suppose is x_test_1
print("test loss, test acc:", results)
19/19 [==============================] - 1s 17ms/step - loss: 0.2496 - accuracy: 0.5133 test loss, test acc: [0.24957270920276642, 0.5133333206176758]
# Visualize the predicted model
def visualize(pairs, labels, to_show=6, num_col=3, predictions=None, test=False):
"""Creates a plot of pairs and labels, and prediction if it's test dataset.
Arguments:
pairs: Numpy Array, of pairs to visualize, having shape
(Number of pairs, 2, 28, 28).
to_show: Int, number of examples to visualize (default is 6)
`to_show` must be an integral multiple of `num_col`.
Otherwise it will be trimmed if it is greater than num_col,
and incremented if if it is less then num_col.
num_col: Int, number of images in one row - (default is 3)
For test and train respectively, it should not exceed 3 and 7.
predictions: Numpy Array of predictions with shape (to_show, 1) -
(default is None)
Must be passed when test=True.
test: Boolean telling whether the dataset being visualized is
train dataset or test dataset - (default False).
Returns:
None.
"""
# Define num_row
# If to_show % num_col != 0
# trim to_show,
# to trim to_show limit num_row to the point where
# to_show % num_col == 0
#
# If to_show//num_col == 0
# then it means num_col is greater then to_show
# increment to_show
# to increment to_show set num_row to 1
num_row = to_show // num_col if to_show // num_col != 0 else 1
# `to_show` must be an integral multiple of `num_col`
# we found num_row and we have num_col
# to increment or decrement to_show
# to make it integral multiple of `num_col`
# simply set it equal to num_row * num_col
to_show = num_row * num_col
# Plot the images
fig, axes = plt.subplots(num_row, num_col, figsize=(5, 5))
for i in range(to_show):
# If the number of rows is 1, the axes array is one-dimensional
if num_row == 1:
ax = axes[i % num_col]
else:
ax = axes[i // num_col, i % num_col]
ax.imshow(tf.concat([pairs[i][0], pairs[i][1]], axis=1))
ax.set_axis_off()
if test:
ax.set_title("True: {} | Pred: {:.5f}".format(labels[i], predictions[i][0]))
else:
ax.set_title("Label: {}".format(labels[i]))
if test:
plt.tight_layout(rect=(0, 0, 1.9, 1.9), w_pad=0.0)
else:
plt.tight_layout(rect=(0, 0, 1.5, 1.5))
plt.show()
# Model Prediction
predictions = siamese.predict([x_val_1, x_val_2])
visualize(pairs_val, labels_val, to_show=3, predictions=predictions, test=True)
from keras.utils.np_utils import to_categorical
categorical_labels_y = to_categorical(y_train, num_classes=3)
categorical_labels_y_val = to_categorical(y_val, num_classes=3)
## encoding the labels
from sklearn.preprocessing import LabelBinarizer
enc = LabelBinarizer()
y2 = enc.fit_transform(y_train)
y2
y2_val = enc.fit_transform(y_val)
# %pip install numba
Requirement already satisfied: numba in c:\anacondapython\envs\tensorflow\lib\site-packages (0.59.0) Requirement already satisfied: llvmlite<0.43,>=0.42.0dev0 in c:\anacondapython\envs\tensorflow\lib\site-packages (from numba) (0.42.0) Requirement already satisfied: numpy<1.27,>=1.22 in c:\anacondapython\envs\tensorflow\lib\site-packages (from numba) (1.22.3) Note: you may need to restart the kernel to use updated packages.
# from numba import cuda
# device = cuda.get_current_device()
# device.reset()
import tensorflow as tf
gpus = tf.config.list_physical_devices('GPU')
print(gpus)
if gpus:
tf.config.set_logical_device_configuration(
gpus[0],
[tf.config.LogicalDeviceConfiguration(memory_limit=5292)]
)
logical_gpus = tf.config.list_logical_devices('GPU')
print(len(gpus), "Physical GPU,", len(logical_gpus), "Logical GPUs")
from tensorflow.keras.applications.vgg16 import VGG16
from tensorflow.keras.applications.vgg16 import preprocess_input
##VGGNet is a well-documented and globally used architecture for convolutional neural network
## Include_top=False to remove the classification layer that was trained on the ImageNet dataset and set the model as not trainable
base_model = VGG16(weights="imagenet", include_top=False, input_shape=x_train[0].shape)
base_model.trainable = False ## Not trainable weights
## Preprocessing input
train_ds = preprocess_input(x_train)
train_val_df = preprocess_input(x_val)
## Adding two hidden later and one softmax layer as an output layer
from tensorflow.keras import layers, models
flatten_layer = layers.Flatten()
dense_layer_1 = layers.Dense(64, activation='relu')
dense_layer_2 = layers.Dense(32, activation='relu')
dense_layer_3 = layers.Dense(16, activation='relu')
prediction_layer = layers.Dense(3, activation='softmax')
cnn_VGG16_model1 = models.Sequential([
base_model,
flatten_layer,
dense_layer_1,
dense_layer_2,
dense_layer_3,
prediction_layer
])
from tensorflow.keras.callbacks import EarlyStopping
cnn_VGG16_model1.compile(
optimizer='Adam',
loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
metrics=['accuracy'],
)
## Early stopping whe validation accuracy does not change for 7 iteration
es = EarlyStopping(monitor='val_accuracy', mode='auto', patience=7, restore_best_weights=True)
#Trainign the model
history = cnn_VGG16_model1.fit(train_ds, y_train, epochs=50, validation_data=(train_val_df,y_val) ,callbacks=es)
Epoch 1/50
C:\AnacondaPython\envs\tensorflow\lib\site-packages\tensorflow\python\util\dispatch.py:1082: UserWarning: "`binary_crossentropy` received `from_logits=True`, but the `output` argument was produced by a sigmoid or softmax activation and thus does not represent logits. Was this intended?" return dispatch_target(*args, **kwargs)
375/375 [==============================] - 32s 68ms/step - loss: 0.6530 - accuracy: 0.3305 - val_loss: 0.6460 - val_accuracy: 0.3307 Epoch 2/50 375/375 [==============================] - 24s 64ms/step - loss: 0.6405 - accuracy: 0.3310 - val_loss: 0.6369 - val_accuracy: 0.3353 Epoch 3/50 375/375 [==============================] - 24s 64ms/step - loss: 0.6379 - accuracy: 0.3375 - val_loss: 0.6385 - val_accuracy: 0.3307 Epoch 4/50 375/375 [==============================] - 24s 65ms/step - loss: 0.6373 - accuracy: 0.3265 - val_loss: 0.6366 - val_accuracy: 0.3353 Epoch 5/50 375/375 [==============================] - 24s 65ms/step - loss: 0.6371 - accuracy: 0.3273 - val_loss: 0.6373 - val_accuracy: 0.3353 Epoch 6/50 375/375 [==============================] - 25s 66ms/step - loss: 0.6370 - accuracy: 0.3324 - val_loss: 0.6376 - val_accuracy: 0.3340 Epoch 7/50 375/375 [==============================] - 25s 66ms/step - loss: 0.6374 - accuracy: 0.3294 - val_loss: 0.6368 - val_accuracy: 0.3307 Epoch 8/50 375/375 [==============================] - 25s 66ms/step - loss: 0.6367 - accuracy: 0.3312 - val_loss: 0.6366 - val_accuracy: 0.3307 Epoch 9/50 375/375 [==============================] - 25s 66ms/step - loss: 0.6366 - accuracy: 0.3399 - val_loss: 0.6368 - val_accuracy: 0.3307
from tensorflow.keras.applications.resnet50 import ResNet50
from tensorflow.keras.applications.resnet50 import preprocess_input
from tensorflow.keras import layers, models
from tensorflow.keras.callbacks import EarlyStopping
resnet_base_model = ResNet50(include_top=False, weights='imagenet', input_shape=x_train[0].shape)
#model = VGG16(include_top=False, weights='imagenet', input_shape=(256,256,3))
train_ds = preprocess_input(x_train)
train_val_df = preprocess_input(x_val)
flatten_layer = layers.Flatten()
dense_layer_1 = layers.Dense(50, activation='relu')
dense_layer_2 = layers.Dense(32, activation='relu')
prediction_layer = layers.Dense(3, activation='softmax')
cnn_resnet_model = models.Sequential([
resnet_base_model,
flatten_layer,
dense_layer_1,
dense_layer_2,
prediction_layer
])
cnn_resnet_model.compile(
optimizer='Adam',
loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
metrics=['accuracy'],
)
history =cnn_resnet_model.fit(train_ds, y_train, epochs=30, validation_data=(train_val_df,y_val))
Epoch 1/30
C:\AnacondaPython\envs\tensorflow\lib\site-packages\tensorflow\python\util\dispatch.py:1082: UserWarning: "`binary_crossentropy` received `from_logits=True`, but the `output` argument was produced by a sigmoid or softmax activation and thus does not represent logits. Was this intended?" return dispatch_target(*args, **kwargs)
38/38 [==============================] - 17s 202ms/step - loss: 0.8836 - accuracy: 0.3617 - val_loss: 20.1972 - val_accuracy: 0.3433 Epoch 2/30 38/38 [==============================] - 5s 139ms/step - loss: 0.6624 - accuracy: 0.3258 - val_loss: 0.6938 - val_accuracy: 0.3433 Epoch 3/30 38/38 [==============================] - 5s 137ms/step - loss: 0.6508 - accuracy: 0.3525 - val_loss: 0.6651 - val_accuracy: 0.3433 Epoch 4/30 38/38 [==============================] - 5s 141ms/step - loss: 0.6436 - accuracy: 0.3583 - val_loss: 0.6702 - val_accuracy: 0.3433 Epoch 5/30 38/38 [==============================] - 5s 141ms/step - loss: 0.6441 - accuracy: 0.3408 - val_loss: 0.6691 - val_accuracy: 0.3433 Epoch 6/30 38/38 [==============================] - 5s 142ms/step - loss: 0.6434 - accuracy: 0.3675 - val_loss: 0.6672 - val_accuracy: 0.3433 Epoch 7/30 38/38 [==============================] - 5s 141ms/step - loss: 0.6380 - accuracy: 0.3708 - val_loss: 0.6726 - val_accuracy: 0.3433 Epoch 8/30 38/38 [==============================] - 5s 142ms/step - loss: 0.6392 - accuracy: 0.3467 - val_loss: 0.7039 - val_accuracy: 0.3433 Epoch 9/30 38/38 [==============================] - 5s 142ms/step - loss: 0.6358 - accuracy: 0.3658 - val_loss: 0.7424 - val_accuracy: 0.3433 Epoch 10/30 38/38 [==============================] - 5s 142ms/step - loss: 0.6453 - accuracy: 0.3450 - val_loss: 0.9945 - val_accuracy: 0.3433 Epoch 11/30 38/38 [==============================] - 5s 142ms/step - loss: 0.6317 - accuracy: 0.3967 - val_loss: 0.8168 - val_accuracy: 0.3433 Epoch 12/30 38/38 [==============================] - 5s 142ms/step - loss: 0.6397 - accuracy: 0.3608 - val_loss: 1.2319 - val_accuracy: 0.3433 Epoch 13/30 38/38 [==============================] - 5s 143ms/step - loss: 0.6371 - accuracy: 0.3592 - val_loss: 3.2688 - val_accuracy: 0.3433 Epoch 14/30 38/38 [==============================] - 5s 143ms/step - loss: 0.6363 - accuracy: 0.3842 - val_loss: 1.8918 - val_accuracy: 0.3433 Epoch 15/30 38/38 [==============================] - 5s 143ms/step - loss: 0.6384 - accuracy: 0.3792 - val_loss: 1.1649 - val_accuracy: 0.3433 Epoch 16/30 38/38 [==============================] - 5s 142ms/step - loss: 0.6327 - accuracy: 0.3967 - val_loss: 4.4296 - val_accuracy: 0.3433 Epoch 17/30 38/38 [==============================] - 5s 143ms/step - loss: 0.6337 - accuracy: 0.3708 - val_loss: 3.9740 - val_accuracy: 0.3433 Epoch 18/30 38/38 [==============================] - 5s 144ms/step - loss: 0.6293 - accuracy: 0.3858 - val_loss: 6.8792 - val_accuracy: 0.3433 Epoch 19/30 38/38 [==============================] - 5s 142ms/step - loss: 0.6317 - accuracy: 0.3867 - val_loss: 5.1242 - val_accuracy: 0.3433 Epoch 20/30 38/38 [==============================] - 5s 144ms/step - loss: 0.6323 - accuracy: 0.3975 - val_loss: 0.6492 - val_accuracy: 0.3133 Epoch 21/30 38/38 [==============================] - 5s 143ms/step - loss: 0.6279 - accuracy: 0.3983 - val_loss: 1.1366 - val_accuracy: 0.3433 Epoch 22/30 38/38 [==============================] - 5s 144ms/step - loss: 0.6368 - accuracy: 0.3725 - val_loss: 1.2165 - val_accuracy: 0.3433 Epoch 23/30 38/38 [==============================] - 5s 142ms/step - loss: 0.6549 - accuracy: 0.3517 - val_loss: 0.9874 - val_accuracy: 0.3433 Epoch 24/30 38/38 [==============================] - 5s 143ms/step - loss: 0.6417 - accuracy: 0.3300 - val_loss: 0.8261 - val_accuracy: 0.3567 Epoch 25/30 38/38 [==============================] - 5s 143ms/step - loss: 0.6423 - accuracy: 0.3558 - val_loss: 0.8302 - val_accuracy: 0.2900 Epoch 26/30 38/38 [==============================] - 5s 144ms/step - loss: 0.6378 - accuracy: 0.3450 - val_loss: 0.8909 - val_accuracy: 0.3433 Epoch 27/30 38/38 [==============================] - 5s 144ms/step - loss: 0.6374 - accuracy: 0.3608 - val_loss: 0.6750 - val_accuracy: 0.3000 Epoch 28/30 38/38 [==============================] - 5s 144ms/step - loss: 0.6326 - accuracy: 0.3625 - val_loss: 0.6392 - val_accuracy: 0.3000 Epoch 29/30 38/38 [==============================] - 5s 144ms/step - loss: 0.6292 - accuracy: 0.4042 - val_loss: 4.9998 - val_accuracy: 0.3433 Epoch 30/30 38/38 [==============================] - 5s 143ms/step - loss: 0.6292 - accuracy: 0.4050 - val_loss: 3.0518 - val_accuracy: 0.3433
from tensorflow.keras.applications.mobilenet import preprocess_input
import pydicom as dcm
images = []
ADJUSTED_IMAGE_SIZE = 128
imageList = []
classLabels = []
labels = []
originalImage = []
# Function to read the image from the path and reshape the image to size
def readAndReshapeImage(image):
img = np.array(image).astype(np.uint8)
## Resize the image
res = cv2.resize(img,(ADJUSTED_IMAGE_SIZE,ADJUSTED_IMAGE_SIZE), interpolation = cv2.INTER_LINEAR)
return res
## Read the imahge and resize the image
def populateImage(rowData):
for index, row in rowData.iterrows():
patientId = row.patientId
classlabel = row["class"]
dcm_file = 'train_images\stage_2_train_images\\'+'{}.dcm'.format(patientId)
dcm_data = dcm.read_file(dcm_file)
img = dcm_data.pixel_array
## Converting the image to 3 channels as the dicom image pixel does not have colour classes wiht it
if len(img.shape) != 3 or img.shape[2] != 3:
img = np.stack((img,) * 3, -1)
imageList.append(readAndReshapeImage(img))
# originalImage.append(img)
classLabels.append(classlabel)
tmpImages = np.array(imageList)
tmpLabels = np.array(classLabels)
# originalImages = np.array(originalImage)
return tmpImages,tmpLabels
labels = pd.read_csv("stage_2_train_labels.csv")
class_labels = pd.read_csv('stage_2_detailed_class_info.csv')
training_data = pd.concat([labels, class_labels['class']], axis = 1)
sample_trainigdata = training_data.groupby('class', group_keys=False).apply(lambda x: x.sample(1000))
images,labels = populateImage(sample_trainigdata)
from sklearn.preprocessing import LabelBinarizer
enc = LabelBinarizer()
y2 = enc.fit_transform(labels)
## splitting into train ,test and validation data
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(images, y2, test_size=0.3, random_state=50)
X_test, X_val, y_test, y_val = train_test_split(X_test,y_test, test_size = 0.5, random_state=50)
## Creating a Copy
X_train1 = X_train.copy()
X_val1 = X_val.copy()
X_test1 = X_test.copy()
import tensorflow as tf
from tensorflow.keras.applications.vgg16 import VGG16
from tensorflow.keras.applications.vgg16 import preprocess_input
from tensorflow.keras import layers, models
from tensorflow.keras.callbacks import EarlyStopping
##VGGNet is a well-documented and globally used architecture for convolutional neural network
## Include_top=False to remove the classification layer that was trained on the ImageNet dataset and set the model as not trainable
base_model = VGG16(weights="imagenet", include_top=False, input_shape=X_train[0].shape)
base_model.trainable = False ## Not trainable weights
## Preprocessing input
train_ds = preprocess_input(X_train1)
train_val_df = preprocess_input(X_val1)
flatten_layer = layers.Flatten()
dense_layer_1 = layers.Dense(50, activation='relu')
dense_layer_2 = layers.Dense(20, activation='relu')
prediction_layer = layers.Dense(3, activation='softmax')
cnn_VGG16_model = models.Sequential([
base_model,
flatten_layer,
dense_layer_1,
dense_layer_2,
prediction_layer
])
cnn_VGG16_model.compile(
optimizer='Adam',
loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
metrics=['accuracy'],
)
## Early stopping whe validation accuracy does not change for 7 iteration
es = EarlyStopping(monitor='val_accuracy', mode='auto', patience=7, restore_best_weights=True)
#Trainign the model
history = cnn_VGG16_model.fit(train_ds, y_train, epochs=30, validation_data=(train_val_df,y_val) ,callbacks=es)
Epoch 1/30
C:\AnacondaPython\envs\tensorflow\lib\site-packages\tensorflow\python\util\dispatch.py:1082: UserWarning: "`binary_crossentropy` received `from_logits=True`, but the `output` argument was produced by a sigmoid or softmax activation and thus does not represent logits. Was this intended?" return dispatch_target(*args, **kwargs)
66/66 [==============================] - 10s 93ms/step - loss: 0.8521 - accuracy: 0.5648 - val_loss: 0.5803 - val_accuracy: 0.6467 Epoch 2/30 66/66 [==============================] - 4s 63ms/step - loss: 0.4586 - accuracy: 0.7033 - val_loss: 0.5100 - val_accuracy: 0.6778 Epoch 3/30 66/66 [==============================] - 4s 62ms/step - loss: 0.3428 - accuracy: 0.7757 - val_loss: 0.5701 - val_accuracy: 0.6400 Epoch 4/30 66/66 [==============================] - 4s 62ms/step - loss: 0.2639 - accuracy: 0.8376 - val_loss: 0.5628 - val_accuracy: 0.6622 Epoch 5/30 66/66 [==============================] - 4s 63ms/step - loss: 0.2190 - accuracy: 0.8743 - val_loss: 0.6210 - val_accuracy: 0.6467 Epoch 6/30 66/66 [==============================] - 4s 63ms/step - loss: 0.1813 - accuracy: 0.9057 - val_loss: 0.6583 - val_accuracy: 0.6733 Epoch 7/30 66/66 [==============================] - 4s 63ms/step - loss: 0.1427 - accuracy: 0.9290 - val_loss: 0.7098 - val_accuracy: 0.6511 Epoch 8/30 66/66 [==============================] - 4s 63ms/step - loss: 0.1239 - accuracy: 0.9362 - val_loss: 0.7691 - val_accuracy: 0.6444 Epoch 9/30 66/66 [==============================] - 4s 64ms/step - loss: 0.1206 - accuracy: 0.9338 - val_loss: 0.8734 - val_accuracy: 0.6178
test_ds = preprocess_input(X_test1)
fcl_loss, fcl_accuracy = cnn_VGG16_model.evaluate(test_ds, y_test, verbose=1)
print('Test loss:', fcl_loss)
print('Test accuracy:', fcl_accuracy)
15/15 [==============================] - 1s 47ms/step - loss: 0.5902 - accuracy: 0.6111 Test loss: 0.5902150869369507 Test accuracy: 0.6111111044883728
from tensorflow.keras.applications.resnet50 import ResNet50
from tensorflow.keras.applications.resnet50 import preprocess_input
from tensorflow.keras import layers, models
from tensorflow.keras.callbacks import EarlyStopping
resnet_base_model = ResNet50(include_top=False, weights='imagenet', input_shape=X_train[0].shape)
#model = VGG16(include_top=False, weights='imagenet', input_shape=(256,256,3))
train_ds = preprocess_input(X_train1)
train_val_df = preprocess_input(X_val1)
flatten_layer = layers.Flatten()
dense_layer_1 = layers.Dense(50, activation='relu')
dense_layer_2 = layers.Dense(32, activation='relu')
prediction_layer = layers.Dense(3, activation='softmax')
cnn_resnet_model = models.Sequential([
resnet_base_model,
flatten_layer,
dense_layer_1,
dense_layer_2,
prediction_layer
])
cnn_resnet_model.compile(
optimizer='Adam',
loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
metrics=['accuracy'],
)
history =cnn_resnet_model.fit(train_ds, y_train, epochs=30, validation_data=(train_val_df,y_val))
Epoch 1/30 66/66 [==============================] - 17s 164ms/step - loss: 0.6438 - accuracy: 0.5767 - val_loss: 23.1146 - val_accuracy: 0.3644 Epoch 2/30 66/66 [==============================] - 9s 133ms/step - loss: 0.4527 - accuracy: 0.6695 - val_loss: 28.1636 - val_accuracy: 0.3933 Epoch 3/30 66/66 [==============================] - 9s 134ms/step - loss: 0.4109 - accuracy: 0.7110 - val_loss: 1.5025 - val_accuracy: 0.6111 Epoch 4/30 66/66 [==============================] - 9s 134ms/step - loss: 0.3874 - accuracy: 0.7276 - val_loss: 5.5881 - val_accuracy: 0.4933 Epoch 5/30 66/66 [==============================] - 9s 135ms/step - loss: 0.3396 - accuracy: 0.7795 - val_loss: 0.5812 - val_accuracy: 0.5933 Epoch 6/30 66/66 [==============================] - 9s 136ms/step - loss: 0.2978 - accuracy: 0.8148 - val_loss: 0.7427 - val_accuracy: 0.5267 Epoch 7/30 66/66 [==============================] - 9s 136ms/step - loss: 0.2899 - accuracy: 0.8176 - val_loss: 3.7301 - val_accuracy: 0.5333 Epoch 8/30 66/66 [==============================] - 9s 135ms/step - loss: 0.2616 - accuracy: 0.8338 - val_loss: 2.2900 - val_accuracy: 0.5311 Epoch 9/30 66/66 [==============================] - 9s 136ms/step - loss: 0.2274 - accuracy: 0.8557 - val_loss: 3.1713 - val_accuracy: 0.3711 Epoch 10/30 66/66 [==============================] - 9s 137ms/step - loss: 0.1993 - accuracy: 0.8781 - val_loss: 0.7005 - val_accuracy: 0.5956 Epoch 11/30 66/66 [==============================] - 9s 137ms/step - loss: 0.1821 - accuracy: 0.8890 - val_loss: 0.9039 - val_accuracy: 0.6067 Epoch 12/30 66/66 [==============================] - 9s 137ms/step - loss: 0.1559 - accuracy: 0.9090 - val_loss: 1.8934 - val_accuracy: 0.5378 Epoch 13/30 66/66 [==============================] - 9s 137ms/step - loss: 0.1361 - accuracy: 0.9229 - val_loss: 0.7330 - val_accuracy: 0.6422 Epoch 14/30 66/66 [==============================] - 9s 137ms/step - loss: 0.1345 - accuracy: 0.9262 - val_loss: 0.7860 - val_accuracy: 0.6200 Epoch 15/30 66/66 [==============================] - 9s 138ms/step - loss: 0.0877 - accuracy: 0.9514 - val_loss: 0.8470 - val_accuracy: 0.6156 Epoch 16/30 66/66 [==============================] - 9s 138ms/step - loss: 0.0838 - accuracy: 0.9552 - val_loss: 3.2672 - val_accuracy: 0.6089 Epoch 17/30 66/66 [==============================] - 9s 138ms/step - loss: 0.0843 - accuracy: 0.9533 - val_loss: 1.2537 - val_accuracy: 0.5867 Epoch 18/30 66/66 [==============================] - 9s 138ms/step - loss: 0.0873 - accuracy: 0.9538 - val_loss: 0.9191 - val_accuracy: 0.6378 Epoch 19/30 66/66 [==============================] - 9s 138ms/step - loss: 0.0811 - accuracy: 0.9610 - val_loss: 1.3638 - val_accuracy: 0.5733 Epoch 20/30 66/66 [==============================] - 9s 138ms/step - loss: 0.0494 - accuracy: 0.9738 - val_loss: 1.1878 - val_accuracy: 0.6022 Epoch 21/30 66/66 [==============================] - 9s 138ms/step - loss: 0.0406 - accuracy: 0.9762 - val_loss: 1.0943 - val_accuracy: 0.6244 Epoch 22/30 66/66 [==============================] - 9s 139ms/step - loss: 0.0487 - accuracy: 0.9762 - val_loss: 1.2896 - val_accuracy: 0.5889 Epoch 23/30 66/66 [==============================] - 9s 138ms/step - loss: 0.0638 - accuracy: 0.9714 - val_loss: 0.9916 - val_accuracy: 0.6178 Epoch 24/30 66/66 [==============================] - 9s 138ms/step - loss: 0.0655 - accuracy: 0.9633 - val_loss: 0.9599 - val_accuracy: 0.6333 Epoch 25/30 66/66 [==============================] - 9s 139ms/step - loss: 0.0437 - accuracy: 0.9790 - val_loss: 1.5358 - val_accuracy: 0.6267 Epoch 26/30 66/66 [==============================] - 9s 138ms/step - loss: 0.0461 - accuracy: 0.9752 - val_loss: 1.0642 - val_accuracy: 0.6067 Epoch 27/30 66/66 [==============================] - 9s 139ms/step - loss: 0.0186 - accuracy: 0.9933 - val_loss: 1.1430 - val_accuracy: 0.6467 Epoch 28/30 66/66 [==============================] - 9s 139ms/step - loss: 0.0113 - accuracy: 0.9957 - val_loss: 1.2538 - val_accuracy: 0.6156 Epoch 29/30 66/66 [==============================] - 9s 139ms/step - loss: 0.0142 - accuracy: 0.9924 - val_loss: 1.2726 - val_accuracy: 0.5978 Epoch 30/30 66/66 [==============================] - 9s 141ms/step - loss: 0.0374 - accuracy: 0.9810 - val_loss: 1.5783 - val_accuracy: 0.6756
fcl_loss, fcl_accuracy = cnn_resnet_model.evaluate(test_ds, y_test, verbose=1)
print('Test loss:', fcl_loss)
print('Test accuracy:', fcl_accuracy)
15/15 [==============================] - 1s 38ms/step - loss: 1.6677 - accuracy: 0.6289 Test loss: 1.667738437652588 Test accuracy: 0.6288889050483704
import os
import csv
import random
import pydicom
import numpy as np
import pandas as pd
from skimage import measure
from skimage.transform import resize
import matplotlib.patches as patches
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow import keras
%matplotlib inline
pneumonia_locations = {}
# load table
with open(os.path.join('stage_2_train_labels.csv'),
'r') as infile:
# open reader
reader = csv.reader(infile)
# skip header
next(reader, None)
# loop through rows
for rows in reader:
# retrieve information
filename = rows[0]
location = rows[1:5]
pneumonia = rows[5]
# if row contains pneumonia add label to dictionary
# which contains a list of pneumonia locations per filename
if pneumonia == '1':
# convert string to float to int
location = [int(float(i)) for i in location]
# save pneumonia location in dictionary
if filename in pneumonia_locations:
pneumonia_locations[filename].append(location)
else:
pneumonia_locations[filename] = [location]
Data generator
The dataset is too large to fit into memory, so we need to create a generator that loads data on the fly.
The generator takes in some filenames, batch_size and other parameters.
The generator outputs a random batch of numpy images and numpy masks.
# load and shuffle filenames
folder = 'train_images/stage_2_train_images'
filenames = os.listdir(folder)
random.shuffle(filenames)
# split into train and validation filenames
n_valid_samples = 2000
train_filenames = filenames[n_valid_samples:4000]
valid_filenames = filenames[:n_valid_samples]
print('n train samples', len(train_filenames))
print('n valid samples', len(valid_filenames))
n_train_samples = len(filenames) - n_valid_samples
n train samples 2000 n valid samples 2000
class generator(keras.utils.Sequence):
def __init__(self, folder, filenames, pneumonia_locations=None, batch_size=32, image_size=256, shuffle=True, augment=False, predict=False):
self.folder = folder
self.filenames = filenames
self.pneumonia_locations = pneumonia_locations
self.batch_size = batch_size
self.image_size = image_size
self.shuffle = shuffle
self.augment = augment
self.predict = predict
self.on_epoch_end()
def __load__(self, filename):
# load dicom file as numpy array
img = pydicom.dcmread(os.path.join(self.folder, filename)).pixel_array
# create empty mask
msk = np.zeros(img.shape)
# get filename without extension
filename = filename.split('.')[0]
# if image contains pneumonia
if filename in self.pneumonia_locations:
# loop through pneumonia
for location in self.pneumonia_locations[filename]:
# add 1's at the location of the pneumonia
x, y, w, h = location
msk[y:y+h, x:x+w] = 1
# resize both image and mask
img = resize(img, (self.image_size, self.image_size), mode='reflect')
msk = resize(msk, (self.image_size, self.image_size), mode='reflect') > 0.5
# if augment then horizontal flip half the time
if self.augment and random.random() > 0.5:
img = np.fliplr(img)
msk = np.fliplr(msk)
# add trailing channel dimension
img = np.expand_dims(img, -1)
msk = np.expand_dims(msk, -1)
return img, msk
def __loadpredict__(self, filename):
# load dicom file as numpy array
img = pydicom.dcmread(os.path.join(self.folder, filename)).pixel_array
# resize image
img = resize(img, (self.image_size, self.image_size), mode='reflect')
# add trailing channel dimension
img = np.expand_dims(img, -1)
return img
def __getitem__(self, index):
# select batch
filenames = self.filenames[index*self.batch_size:(index+1)*self.batch_size]
# predict mode: return images and filenames
if self.predict:
# load files
imgs = [self.__loadpredict__(filename) for filename in filenames]
# create numpy batch
imgs = np.array(imgs)
return imgs, filenames
# train mode: return images and masks
else:
# load files
items = [self.__load__(filename) for filename in filenames]
# unzip images and masks
imgs, msks = zip(*items)
# create numpy batch
imgs = np.array(imgs)
msks = np.array(msks)
return imgs, msks
def on_epoch_end(self):
if self.shuffle:
random.shuffle(self.filenames)
def __len__(self):
if self.predict:
# return everything
return int(np.ceil(len(self.filenames) / self.batch_size))
else:
# return full batches only
return int(len(self.filenames) / self.batch_size)
# define iou or jaccard loss function
def iou_loss(y_true, y_pred):
#print(y_true)
y_true=tf.cast(y_true, tf.float32)
y_pred=tf.cast(y_pred, tf.float32)
y_true = tf.reshape(y_true, [-1])
y_pred = tf.reshape(y_pred, [-1])
intersection = tf.reduce_sum(y_true * y_pred)
score = (intersection + 1.) / (tf.reduce_sum(y_true) + tf.reduce_sum(y_pred) - intersection + 1.)
return 1 - score
# combine bce loss and iou loss
def iou_bce_loss(y_true, y_pred):
return 0.5 * keras.losses.binary_crossentropy(y_true, y_pred) + 0.5 * iou_loss(y_true, y_pred)
# mean iou as a metric
def mean_iou(y_true, y_pred):
y_pred = tf.round(y_pred)
intersect = tf.reduce_sum(y_true * y_pred, axis=[1, 2, 3])
union = tf.reduce_sum(y_true, axis=[1, 2, 3]) + tf.reduce_sum(y_pred, axis=[1, 2, 3])
smooth = tf.ones(tf.shape(intersect))
return tf.reduce_mean((intersect + smooth) / (union - intersect + smooth))
def create_downsample(channels, inputs):
x = keras.layers.BatchNormalization(momentum=0.9)(inputs)
x = keras.layers.LeakyReLU(0)(x)
x = keras.layers.Conv2D(channels, 1, padding='same', use_bias=False)(x)
x = keras.layers.MaxPool2D(2)(x)
return x
def create_resblock(channels, inputs):
x = keras.layers.BatchNormalization(momentum=0.9)(inputs)
x = keras.layers.LeakyReLU(0)(x)
x = keras.layers.Conv2D(channels, 3, padding='same', use_bias=False)(x)
x = keras.layers.BatchNormalization(momentum=0.9)(x)
x = keras.layers.LeakyReLU(0)(x)
x = keras.layers.Conv2D(channels, 3, padding='same', use_bias=False)(x)
return keras.layers.add([x, inputs])
def create_network(input_size, channels, n_blocks=2, depth=4):
# input
inputs = keras.Input(shape=(input_size, input_size, 1))
x = keras.layers.Conv2D(channels, 3, padding='same', use_bias=False)(inputs)
# residual blocks
for d in range(depth):
channels = channels * 2
x = create_downsample(channels, x)
for b in range(n_blocks):
x = create_resblock(channels, x)
# output
x = keras.layers.BatchNormalization(momentum=0.9)(x)
x = keras.layers.LeakyReLU(0)(x)
x = keras.layers.Conv2D(1, 1, activation='sigmoid')(x)
outputs = keras.layers.UpSampling2D(2**depth)(x)
model = keras.Model(inputs=inputs, outputs=outputs)
return model
BATCH_SIZE = 16
IMAGE_SIZE = 128
model = create_network(input_size=IMAGE_SIZE, channels=32, n_blocks=2, depth=4)
model.compile(optimizer='adam', loss=iou_bce_loss, metrics=['accuracy', mean_iou])
# cosine learning rate annealing
def cosine_annealing(x):
lr = 0.0001
epochs = 3
return lr*(np.cos(np.pi*x/epochs)+1.)/2
learning_rate = tf.keras.callbacks.LearningRateScheduler(cosine_annealing)
# create train and validation generators
folder = 'train_images\\stage_2_train_images\\'
train_gen = generator(folder, train_filenames, pneumonia_locations, batch_size=BATCH_SIZE,
image_size=IMAGE_SIZE, shuffle=True, augment=False, predict=False)
valid_gen = generator(folder, valid_filenames, pneumonia_locations, batch_size=BATCH_SIZE,
image_size=IMAGE_SIZE, shuffle=False, predict=False)
print(model.summary())
Model: "model_3"
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_4 (InputLayer) [(None, 128, 128, 1 0 []
)]
conv2d_66 (Conv2D) (None, 128, 128, 32 288 ['input_4[0][0]']
)
batch_normalization_63 (BatchN (None, 128, 128, 32 128 ['conv2d_66[0][0]']
ormalization) )
leaky_re_lu_63 (LeakyReLU) (None, 128, 128, 32 0 ['batch_normalization_63[0][0]']
)
conv2d_67 (Conv2D) (None, 128, 128, 64 2048 ['leaky_re_lu_63[0][0]']
)
max_pooling2d_12 (MaxPooling2D (None, 64, 64, 64) 0 ['conv2d_67[0][0]']
)
batch_normalization_64 (BatchN (None, 64, 64, 64) 256 ['max_pooling2d_12[0][0]']
ormalization)
leaky_re_lu_64 (LeakyReLU) (None, 64, 64, 64) 0 ['batch_normalization_64[0][0]']
conv2d_68 (Conv2D) (None, 64, 64, 64) 36864 ['leaky_re_lu_64[0][0]']
batch_normalization_65 (BatchN (None, 64, 64, 64) 256 ['conv2d_68[0][0]']
ormalization)
leaky_re_lu_65 (LeakyReLU) (None, 64, 64, 64) 0 ['batch_normalization_65[0][0]']
conv2d_69 (Conv2D) (None, 64, 64, 64) 36864 ['leaky_re_lu_65[0][0]']
add_24 (Add) (None, 64, 64, 64) 0 ['conv2d_69[0][0]',
'max_pooling2d_12[0][0]']
batch_normalization_66 (BatchN (None, 64, 64, 64) 256 ['add_24[0][0]']
ormalization)
leaky_re_lu_66 (LeakyReLU) (None, 64, 64, 64) 0 ['batch_normalization_66[0][0]']
conv2d_70 (Conv2D) (None, 64, 64, 64) 36864 ['leaky_re_lu_66[0][0]']
batch_normalization_67 (BatchN (None, 64, 64, 64) 256 ['conv2d_70[0][0]']
ormalization)
leaky_re_lu_67 (LeakyReLU) (None, 64, 64, 64) 0 ['batch_normalization_67[0][0]']
conv2d_71 (Conv2D) (None, 64, 64, 64) 36864 ['leaky_re_lu_67[0][0]']
add_25 (Add) (None, 64, 64, 64) 0 ['conv2d_71[0][0]',
'add_24[0][0]']
batch_normalization_68 (BatchN (None, 64, 64, 64) 256 ['add_25[0][0]']
ormalization)
leaky_re_lu_68 (LeakyReLU) (None, 64, 64, 64) 0 ['batch_normalization_68[0][0]']
conv2d_72 (Conv2D) (None, 64, 64, 128) 8192 ['leaky_re_lu_68[0][0]']
max_pooling2d_13 (MaxPooling2D (None, 32, 32, 128) 0 ['conv2d_72[0][0]']
)
batch_normalization_69 (BatchN (None, 32, 32, 128) 512 ['max_pooling2d_13[0][0]']
ormalization)
leaky_re_lu_69 (LeakyReLU) (None, 32, 32, 128) 0 ['batch_normalization_69[0][0]']
conv2d_73 (Conv2D) (None, 32, 32, 128) 147456 ['leaky_re_lu_69[0][0]']
batch_normalization_70 (BatchN (None, 32, 32, 128) 512 ['conv2d_73[0][0]']
ormalization)
leaky_re_lu_70 (LeakyReLU) (None, 32, 32, 128) 0 ['batch_normalization_70[0][0]']
conv2d_74 (Conv2D) (None, 32, 32, 128) 147456 ['leaky_re_lu_70[0][0]']
add_26 (Add) (None, 32, 32, 128) 0 ['conv2d_74[0][0]',
'max_pooling2d_13[0][0]']
batch_normalization_71 (BatchN (None, 32, 32, 128) 512 ['add_26[0][0]']
ormalization)
leaky_re_lu_71 (LeakyReLU) (None, 32, 32, 128) 0 ['batch_normalization_71[0][0]']
conv2d_75 (Conv2D) (None, 32, 32, 128) 147456 ['leaky_re_lu_71[0][0]']
batch_normalization_72 (BatchN (None, 32, 32, 128) 512 ['conv2d_75[0][0]']
ormalization)
leaky_re_lu_72 (LeakyReLU) (None, 32, 32, 128) 0 ['batch_normalization_72[0][0]']
conv2d_76 (Conv2D) (None, 32, 32, 128) 147456 ['leaky_re_lu_72[0][0]']
add_27 (Add) (None, 32, 32, 128) 0 ['conv2d_76[0][0]',
'add_26[0][0]']
batch_normalization_73 (BatchN (None, 32, 32, 128) 512 ['add_27[0][0]']
ormalization)
leaky_re_lu_73 (LeakyReLU) (None, 32, 32, 128) 0 ['batch_normalization_73[0][0]']
conv2d_77 (Conv2D) (None, 32, 32, 256) 32768 ['leaky_re_lu_73[0][0]']
max_pooling2d_14 (MaxPooling2D (None, 16, 16, 256) 0 ['conv2d_77[0][0]']
)
batch_normalization_74 (BatchN (None, 16, 16, 256) 1024 ['max_pooling2d_14[0][0]']
ormalization)
leaky_re_lu_74 (LeakyReLU) (None, 16, 16, 256) 0 ['batch_normalization_74[0][0]']
conv2d_78 (Conv2D) (None, 16, 16, 256) 589824 ['leaky_re_lu_74[0][0]']
batch_normalization_75 (BatchN (None, 16, 16, 256) 1024 ['conv2d_78[0][0]']
ormalization)
leaky_re_lu_75 (LeakyReLU) (None, 16, 16, 256) 0 ['batch_normalization_75[0][0]']
conv2d_79 (Conv2D) (None, 16, 16, 256) 589824 ['leaky_re_lu_75[0][0]']
add_28 (Add) (None, 16, 16, 256) 0 ['conv2d_79[0][0]',
'max_pooling2d_14[0][0]']
batch_normalization_76 (BatchN (None, 16, 16, 256) 1024 ['add_28[0][0]']
ormalization)
leaky_re_lu_76 (LeakyReLU) (None, 16, 16, 256) 0 ['batch_normalization_76[0][0]']
conv2d_80 (Conv2D) (None, 16, 16, 256) 589824 ['leaky_re_lu_76[0][0]']
batch_normalization_77 (BatchN (None, 16, 16, 256) 1024 ['conv2d_80[0][0]']
ormalization)
leaky_re_lu_77 (LeakyReLU) (None, 16, 16, 256) 0 ['batch_normalization_77[0][0]']
conv2d_81 (Conv2D) (None, 16, 16, 256) 589824 ['leaky_re_lu_77[0][0]']
add_29 (Add) (None, 16, 16, 256) 0 ['conv2d_81[0][0]',
'add_28[0][0]']
batch_normalization_78 (BatchN (None, 16, 16, 256) 1024 ['add_29[0][0]']
ormalization)
leaky_re_lu_78 (LeakyReLU) (None, 16, 16, 256) 0 ['batch_normalization_78[0][0]']
conv2d_82 (Conv2D) (None, 16, 16, 512) 131072 ['leaky_re_lu_78[0][0]']
max_pooling2d_15 (MaxPooling2D (None, 8, 8, 512) 0 ['conv2d_82[0][0]']
)
batch_normalization_79 (BatchN (None, 8, 8, 512) 2048 ['max_pooling2d_15[0][0]']
ormalization)
leaky_re_lu_79 (LeakyReLU) (None, 8, 8, 512) 0 ['batch_normalization_79[0][0]']
conv2d_83 (Conv2D) (None, 8, 8, 512) 2359296 ['leaky_re_lu_79[0][0]']
batch_normalization_80 (BatchN (None, 8, 8, 512) 2048 ['conv2d_83[0][0]']
ormalization)
leaky_re_lu_80 (LeakyReLU) (None, 8, 8, 512) 0 ['batch_normalization_80[0][0]']
conv2d_84 (Conv2D) (None, 8, 8, 512) 2359296 ['leaky_re_lu_80[0][0]']
add_30 (Add) (None, 8, 8, 512) 0 ['conv2d_84[0][0]',
'max_pooling2d_15[0][0]']
batch_normalization_81 (BatchN (None, 8, 8, 512) 2048 ['add_30[0][0]']
ormalization)
leaky_re_lu_81 (LeakyReLU) (None, 8, 8, 512) 0 ['batch_normalization_81[0][0]']
conv2d_85 (Conv2D) (None, 8, 8, 512) 2359296 ['leaky_re_lu_81[0][0]']
batch_normalization_82 (BatchN (None, 8, 8, 512) 2048 ['conv2d_85[0][0]']
ormalization)
leaky_re_lu_82 (LeakyReLU) (None, 8, 8, 512) 0 ['batch_normalization_82[0][0]']
conv2d_86 (Conv2D) (None, 8, 8, 512) 2359296 ['leaky_re_lu_82[0][0]']
add_31 (Add) (None, 8, 8, 512) 0 ['conv2d_86[0][0]',
'add_30[0][0]']
batch_normalization_83 (BatchN (None, 8, 8, 512) 2048 ['add_31[0][0]']
ormalization)
leaky_re_lu_83 (LeakyReLU) (None, 8, 8, 512) 0 ['batch_normalization_83[0][0]']
conv2d_87 (Conv2D) (None, 8, 8, 1) 513 ['leaky_re_lu_83[0][0]']
up_sampling2d_3 (UpSampling2D) (None, 128, 128, 1) 0 ['conv2d_87[0][0]']
==================================================================================================
Total params: 12,727,969
Trainable params: 12,718,305
Non-trainable params: 9,664
__________________________________________________________________________________________________
None
EPOCHS=5
# MULTI_PROCESSING = True
history = model.fit(train_gen, validation_data=valid_gen, callbacks=[learning_rate], epochs=EPOCHS)
Epoch 1/5 125/125 [==============================] - 445s 4s/step - loss: 0.5347 - accuracy: 0.9523 - mean_iou: 0.5635 - val_loss: 0.4880 - val_accuracy: 0.9713 - val_mean_iou: 0.7106 - lr: 1.0000e-04 Epoch 2/5 125/125 [==============================] - 315s 3s/step - loss: 0.4759 - accuracy: 0.9632 - mean_iou: 0.6686 - val_loss: 0.4665 - val_accuracy: 0.9655 - val_mean_iou: 0.7236 - lr: 7.5000e-05 Epoch 3/5 125/125 [==============================] - 308s 2s/step - loss: 0.4533 - accuracy: 0.9656 - mean_iou: 0.6945 - val_loss: 0.4606 - val_accuracy: 0.9630 - val_mean_iou: 0.6797 - lr: 2.5000e-05 Epoch 4/5 125/125 [==============================] - 311s 2s/step - loss: 0.4348 - accuracy: 0.9685 - mean_iou: 0.7154 - val_loss: 0.4569 - val_accuracy: 0.9681 - val_mean_iou: 0.7140 - lr: 0.0000e+00 Epoch 5/5 125/125 [==============================] - 313s 3s/step - loss: 0.4382 - accuracy: 0.9689 - mean_iou: 0.7224 - val_loss: 0.4579 - val_accuracy: 0.9630 - val_mean_iou: 0.6908 - lr: 2.5000e-05
plt.figure(figsize=(12,4))
plt.subplot(131)
plt.plot(history.epoch, history.history["loss"], label="Train loss")
plt.plot(history.epoch, history.history["val_loss"], label="Valid loss")
plt.legend()
plt.subplot(132)
plt.plot(history.epoch, history.history["accuracy"], label="Train accuracy")
plt.plot(history.epoch, history.history["val_accuracy"], label="Valid accuracy")
plt.legend()
plt.subplot(133)
plt.plot(history.epoch, history.history["mean_iou"], label="Train iou")
plt.plot(history.epoch, history.history["val_mean_iou"], label="Valid iou")
plt.legend()
plt.show()
i=0
for imgs, msks in valid_gen:
# predict batch of images
preds = model.predict(imgs)
# create figure
f, axarr = plt.subplots(4, 4, figsize=(20,15))
axarr = axarr.ravel()
axidx = 0
# loop through batch
for img, msk, pred in zip(imgs, msks, preds):
i=i+1
#exit after 32 images
if i>16:
break
# plot image
axarr[axidx].imshow(img[:, :, 0])
# threshold true mask
comp = msk[:, :, 0] > 0.5
# apply connected components
comp = measure.label(comp)
# apply bounding boxes
predictionString = ''
for region in measure.regionprops(comp):
# retrieve x, y, height and width
y, x, y2, x2 = region.bbox
height = y2 - y
width = x2 - x
axarr[axidx].add_patch(patches.Rectangle((x,y),width,height,linewidth=2,
edgecolor='b',facecolor='none'))
# threshold predicted mask
comp = pred[:, :, 0] > 0.5
# apply connected components
comp = measure.label(comp)
# apply bounding boxes
predictionString = ''
for region in measure.regionprops(comp):
# retrieve x, y, height and width
y, x, y2, x2 = region.bbox
height = y2 - y
width = x2 - x
axarr[axidx].add_patch(patches.Rectangle((x,y),width,height,linewidth=2,
edgecolor='r',facecolor='none'))
axidx += 1
plt.show()
# only plot one batch
break
!git clone https://github.com/kamlesh364/Mask-RCNN-TF2.7.0-keras2.7.0
Cloning into 'Mask-RCNN-TF2.7.0-keras2.7.0'...
%pip install imgaug
Requirement already satisfied: imgaug in c:\anacondapython\envs\tensorflow\lib\site-packages (0.4.0) Requirement already satisfied: opencv-python in c:\anacondapython\envs\tensorflow\lib\site-packages (from imgaug) (4.9.0.80) Requirement already satisfied: Pillow in c:\anacondapython\envs\tensorflow\lib\site-packages (from imgaug) (9.0.1) Requirement already satisfied: scikit-image>=0.14.2 in c:\anacondapython\envs\tensorflow\lib\site-packages (from imgaug) (0.22.0) Requirement already satisfied: scipy in c:\anacondapython\envs\tensorflow\lib\site-packages (from imgaug) (1.8.0) Requirement already satisfied: imageio in c:\anacondapython\envs\tensorflow\lib\site-packages (from imgaug) (2.34.0) Requirement already satisfied: numpy>=1.15 in c:\anacondapython\envs\tensorflow\lib\site-packages (from imgaug) (1.22.3) Requirement already satisfied: Shapely in c:\anacondapython\envs\tensorflow\lib\site-packages (from imgaug) (2.0.3) Requirement already satisfied: six in c:\anacondapython\envs\tensorflow\lib\site-packages (from imgaug) (1.16.0) Requirement already satisfied: matplotlib in c:\users\jay patadia\appdata\roaming\python\python39\site-packages (from imgaug) (3.5.1) Requirement already satisfied: tifffile>=2022.8.12 in c:\anacondapython\envs\tensorflow\lib\site-packages (from scikit-image>=0.14.2->imgaug) (2024.2.12) Requirement already satisfied: lazy_loader>=0.3 in c:\anacondapython\envs\tensorflow\lib\site-packages (from scikit-image>=0.14.2->imgaug) (0.3) Requirement already satisfied: networkx>=2.8 in c:\anacondapython\envs\tensorflow\lib\site-packages (from scikit-image>=0.14.2->imgaug) (3.2.1) Requirement already satisfied: packaging>=21 in c:\anacondapython\envs\tensorflow\lib\site-packages (from scikit-image>=0.14.2->imgaug) (21.3) Requirement already satisfied: pyparsing!=3.0.5,>=2.0.2 in c:\anacondapython\envs\tensorflow\lib\site-packages (from packaging>=21->scikit-image>=0.14.2->imgaug) (3.0.4) Requirement already satisfied: kiwisolver>=1.0.1 in c:\anacondapython\envs\tensorflow\lib\site-packages (from matplotlib->imgaug) (1.3.2) Requirement already satisfied: cycler>=0.10 in c:\users\jay patadia\appdata\roaming\python\python39\site-packages (from matplotlib->imgaug) (0.11.0) Requirement already satisfied: python-dateutil>=2.7 in c:\anacondapython\envs\tensorflow\lib\site-packages (from matplotlib->imgaug) (2.8.2) Requirement already satisfied: fonttools>=4.22.0 in c:\anacondapython\envs\tensorflow\lib\site-packages (from matplotlib->imgaug) (4.29.1) Note: you may need to restart the kernel to use updated packages.
ROOT_DIR = 'D://Learrning//great learning//capston Proj//dataset'
DATA_DIR = 'D://Learrning//great learning//capston Proj//dataset//train_images'
DATA_DIR_test = 'D://Learrning//great learning//capston Proj//dataset//test_images'
import os
import sys
import random
import math
import numpy as np
import cv2
import matplotlib.pyplot as plt
import json
import pydicom
from imgaug import augmenters as iaa
from tqdm import tqdm
import pandas as pd
import glob
from sklearn.model_selection import KFold
import tensorflow as tf
# Import Mask RCNN
sys.path.append(os.path.join(ROOT_DIR, 'Mask_RCNN')) # To find local version of the library
from mrcnn.config import Config
from mrcnn import utils
import mrcnn.model as modellib
from mrcnn import visualize
from mrcnn.model import log
train_dicom_dir = os.path.join(DATA_DIR, 'stage_2_train_images')
test_dicom_dir = os.path.join(DATA_DIR_test, 'stage_2_test_images')
download the file from " https://github.com/matterport/Mask_RCNN/releases/download/v2.0/mask_rcnn_coco.h5
COCO_WEIGHTS_PATH = "D:\Learrning\great learning\capston Proj\dataset\mask_rcnn_coco.h5"
def get_dicom_fps(dicom_dir):
dicom_fps = glob.glob(dicom_dir+'/'+'*.dcm')
return list(set(dicom_fps))
def parse_dataset(dicom_dir, anns):
print(dicom_dir)
image_fps = get_dicom_fps(dicom_dir)
image_annotations = {fp: [] for fp in image_fps}
for index, row in anns.iterrows():
fp = os.path.join(dicom_dir, row['patientId']+'.dcm')
image_annotations[fp].append(row)
return image_fps, image_annotations
# The following parameters have been selected to reduce running time for demonstration purposes
# These are not optimal
class DetectorConfig(Config):
"""Configuration for training pneumonia detection on the RSNA pneumonia dataset.
Overrides values in the base Config class.
"""
# Give the configuration a recognizable name
NAME = 'pneumonia'
# Train on 1 GPU and 8 images per GPU. We can put multiple images on each
# GPU because the images are small. Batch size is 8 (GPUs * images/GPU).
GPU_COUNT = 1
IMAGES_PER_GPU = 8
BACKBONE = 'resnet50' #vgg16,resnet151
NUM_CLASSES = 2 # background + 1 pneumonia classes
IMAGE_MIN_DIM = 128
IMAGE_MAX_DIM = 128
RPN_ANCHOR_SCALES = (16, 32, 64, 128)
TRAIN_ROIS_PER_IMAGE = 32
MAX_GT_INSTANCES = 4
DETECTION_MAX_INSTANCES = 3
DETECTION_MIN_CONFIDENCE = 0.78 ## match target distribution
DETECTION_NMS_THRESHOLD = 0.01
STEPS_PER_EPOCH = 200
config = DetectorConfig()
config.display()
Configurations:
BACKBONE resnet50
BACKBONE_STRIDES [4, 8, 16, 32, 64]
BATCH_SIZE 8
BBOX_STD_DEV [0.1 0.1 0.2 0.2]
COMPUTE_BACKBONE_SHAPE None
DETECTION_MAX_INSTANCES 3
DETECTION_MIN_CONFIDENCE 0.78
DETECTION_NMS_THRESHOLD 0.01
FPN_CLASSIF_FC_LAYERS_SIZE 1024
GPU_COUNT 1
GRADIENT_CLIP_NORM 5.0
IMAGES_PER_GPU 8
IMAGE_CHANNEL_COUNT 3
IMAGE_MAX_DIM 128
IMAGE_META_SIZE 14
IMAGE_MIN_DIM 128
IMAGE_MIN_SCALE 0
IMAGE_RESIZE_MODE square
IMAGE_SHAPE [128 128 3]
LEARNING_MOMENTUM 0.9
LEARNING_RATE 0.001
LOSS_WEIGHTS {'rpn_class_loss': 1.0, 'rpn_bbox_loss': 1.0, 'mrcnn_class_loss': 1.0, 'mrcnn_bbox_loss': 1.0, 'mrcnn_mask_loss': 1.0}
MASK_POOL_SIZE 14
MASK_SHAPE [28, 28]
MAX_GT_INSTANCES 4
MEAN_PIXEL [123.7 116.8 103.9]
MINI_MASK_SHAPE (56, 56)
NAME pneumonia
NUM_CLASSES 2
POOL_SIZE 7
POST_NMS_ROIS_INFERENCE 1000
POST_NMS_ROIS_TRAINING 2000
PRE_NMS_LIMIT 6000
ROI_POSITIVE_RATIO 0.33
RPN_ANCHOR_RATIOS [0.5, 1, 2]
RPN_ANCHOR_SCALES (16, 32, 64, 128)
RPN_ANCHOR_STRIDE 1
RPN_BBOX_STD_DEV [0.1 0.1 0.2 0.2]
RPN_NMS_THRESHOLD 0.7
RPN_TRAIN_ANCHORS_PER_IMAGE 256
STEPS_PER_EPOCH 200
TOP_DOWN_PYRAMID_SIZE 256
TRAIN_BN False
TRAIN_ROIS_PER_IMAGE 32
USE_MINI_MASK False
USE_RPN_ROIS True
VALIDATION_STEPS 10
WEIGHT_DECAY 0.0001
class DetectorDataset(utils.Dataset):
"""Dataset class for training pneumonia detection on the RSNA pneumonia dataset.
"""
def __init__(self, image_fps, image_annotations, orig_height, orig_width):
super().__init__(self)
# Add classes
self.add_class('pneumonia', 1, 'Lung Opacity')
# add images
for i, fp in enumerate(image_fps):
annotations = image_annotations[fp]
self.add_image('pneumonia', image_id=i, path=fp,
annotations=annotations, orig_height=orig_height, orig_width=orig_width)
def image_reference(self, image_id):
info = self.image_info[image_id]
return info['path']
def load_image(self, image_id):
info = self.image_info[image_id]
fp = info['path']
ds = pydicom.read_file(fp)
image = ds.pixel_array
# If grayscale. Convert to RGB for consistency.
if len(image.shape) != 3 or image.shape[2] != 3:
image = np.stack((image,) * 3, -1)
return image
def load_mask(self, image_id):
info = self.image_info[image_id]
annotations = info['annotations']
count = len(annotations)
if count == 0:
mask = np.zeros((info['orig_height'], info['orig_width'], 1), dtype=np.uint8)
class_ids = np.zeros((1,), dtype=np.int32)
else:
mask = np.zeros((info['orig_height'], info['orig_width'], count), dtype=np.uint8)
class_ids = np.zeros((count,), dtype=np.int32)
for i, a in enumerate(annotations):
if a['Target'] == 1:
x = int(a['x'])
y = int(a['y'])
w = int(a['width'])
h = int(a['height'])
mask_instance = mask[:, :, i].copy()
cv2.rectangle(mask_instance, (x, y), (x+w, y+h), 255, -1)
mask[:, :, i] = mask_instance
class_ids[i] = 1
return mask.astype(np.bool), class_ids.astype(np.int32)
anns = pd.read_csv('D:\Learrning\great learning\capston Proj\dataset\stage_2_train_labels.csv')
anns.head()
| patientId | x | y | width | height | Target | |
|---|---|---|---|---|---|---|
| 0 | 0004cfab-14fd-4e49-80ba-63a80b6bddd6 | NaN | NaN | NaN | NaN | 0 |
| 1 | 00313ee0-9eaa-42f4-b0ab-c148ed3241cd | NaN | NaN | NaN | NaN | 0 |
| 2 | 00322d4d-1c29-4943-afc9-b6754be640eb | NaN | NaN | NaN | NaN | 0 |
| 3 | 003d8fa0-6bf1-40ed-b54c-ac657f8495c5 | NaN | NaN | NaN | NaN | 0 |
| 4 | 00436515-870c-4b36-a041-de91049b9ab4 | 264.0 | 152.0 | 213.0 | 379.0 | 1 |
image_fps, image_annotations = parse_dataset(train_dicom_dir, anns=anns)
D://Learrning//great learning//capston Proj//dataset//train_images\stage_2_train_images
ds = pydicom.read_file(image_fps[0]) # read dicom image from filepath
image = ds.pixel_array # get image array
# Original DICOM image size: 1024 x 1024
ORIG_SIZE = 1024
image_fps_list = list(image_fps)
random.seed(42)
random.shuffle(image_fps_list)
val_size = 1500
image_fps_val = image_fps_list[:val_size]
image_fps_train = image_fps_list[val_size:]
print(len(image_fps_train), len(image_fps_val))
25184 1500
# prepare the training dataset
dataset_train = DetectorDataset(image_fps_train, image_annotations, ORIG_SIZE, ORIG_SIZE)
dataset_train.prepare()
# Show annotation(s) for a DICOM image
test_fp = random.choice(image_fps_train)
image_annotations[test_fp]
# prepare the validation dataset
dataset_val = DetectorDataset(image_fps_val, image_annotations, ORIG_SIZE, ORIG_SIZE)
dataset_val.prepare()
# Load and display random sample and their bounding boxes
class_ids = [0]
while class_ids[0] == 0: ## look for a mask
image_id = random.choice(dataset_train.image_ids)
image_fp = dataset_train.image_reference(image_id)
image = dataset_train.load_image(image_id)
mask, class_ids = dataset_train.load_mask(image_id)
print(image.shape)
plt.figure(figsize=(10, 10))
plt.subplot(1, 2, 1)
plt.imshow(image)
plt.axis('off')
plt.subplot(1, 2, 2)
masked = np.zeros(image.shape[:2])
for i in range(mask.shape[2]):
masked += image[:, :, 0] * mask[:, :, i]
plt.imshow(masked, cmap='gray')
plt.axis('off')
print(image_fp)
print(class_ids)
C:\Users\JAYPAT~1\AppData\Local\Temp/ipykernel_2256/2832466733.py:51: DeprecationWarning: `np.bool` is a deprecated alias for the builtin `bool`. To silence this warning, use `bool` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.bool_` here. Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations return mask.astype(np.bool), class_ids.astype(np.int32)
(1024, 1024, 3) D://Learrning//great learning//capston Proj//dataset//train_images\stage_2_train_images\b77ab795-de76-4715-b371-eb7be54b584c.dcm [1 1]
# Image augmentation (light but constant)
augmentation = iaa.Sequential([
iaa.OneOf([ ## geometric transform
iaa.Affine(
scale={"x": (0.98, 1.02), "y": (0.98, 1.04)},
translate_percent={"x": (-0.02, 0.02), "y": (-0.04, 0.04)},
rotate=(-2, 2),
shear=(-1, 1),
),
iaa.PiecewiseAffine(scale=(0.001, 0.025)),
]),
iaa.OneOf([ ## brightness or contrast
iaa.Multiply((0.9, 1.1)),
iaa.ContrastNormalization((0.9, 1.1)),
]),
iaa.OneOf([ ## blur or sharpen
iaa.GaussianBlur(sigma=(0.0, 0.1)),
iaa.Sharpen(alpha=(0.0, 0.1)),
]),
])
# test on the same image as above
imggrid = augmentation.draw_grid(image[:, :, 0], cols=5, rows=2)
plt.figure(figsize=(30, 12))
_ = plt.imshow(imggrid[:, :, 0], cmap='gray')
C:\AnacondaPython\envs\tensorflow\lib\site-packages\imgaug\imgaug.py:184: DeprecationWarning: Function `ContrastNormalization()` is deprecated. Use `imgaug.contrast.LinearContrast` instead. warn_deprecated(msg, stacklevel=3)
print(tf.__version__)
2.8.0
model = modellib.MaskRCNN(mode='training', model_dir=ROOT_DIR,config=config)
# Exclude the last layers because they require a matching
# number of classes
model.load_weights(COCO_WEIGHTS_PATH, by_name=True, exclude=[
"mrcnn_class_logits", "mrcnn_bbox_fc",
"mrcnn_bbox", "mrcnn_mask"])
LEARNING_RATE = 0.0006
# Train Mask-RCNN Model
import warnings
warnings.filterwarnings("ignore")
%%time
## train heads with higher lr to speedup the learning
history = model.train(dataset_train, dataset_val,
learning_rate=LEARNING_RATE*2,
epochs=2,
layers='heads',
augmentation=None) ## no need to augment yet
# history = model.keras_model.history.history
Starting at epoch 0. LR=0.0012
Checkpoint Path: D://Learrning//great learning//capston Proj//dataset\pneumonia20240320T2057\mask_rcnn_pneumonia_{epoch:04d}.h5
Selecting layers to train
fpn_c5p5 (Conv2D)
fpn_c4p4 (Conv2D)
fpn_c3p3 (Conv2D)
fpn_c2p2 (Conv2D)
fpn_p5 (Conv2D)
fpn_p2 (Conv2D)
fpn_p3 (Conv2D)
fpn_p4 (Conv2D)
rpn_model (Functional)
mrcnn_mask_conv1 (TimeDistributed)
mrcnn_mask_bn1 (TimeDistributed)
mrcnn_mask_conv2 (TimeDistributed)
mrcnn_mask_bn2 (TimeDistributed)
mrcnn_class_conv1 (TimeDistributed)
mrcnn_class_bn1 (TimeDistributed)
mrcnn_mask_conv3 (TimeDistributed)
mrcnn_mask_bn3 (TimeDistributed)
mrcnn_class_conv2 (TimeDistributed)
mrcnn_class_bn2 (TimeDistributed)
mrcnn_mask_conv4 (TimeDistributed)
mrcnn_mask_bn4 (TimeDistributed)
mrcnn_bbox_fc (TimeDistributed)
mrcnn_mask_deconv (TimeDistributed)
mrcnn_class_logits (TimeDistributed)
mrcnn_mask (TimeDistributed)
Epoch 1/2
200/200 [==============================] - 774s 4s/step - batch: 99.5000 - size: 8.0000 - loss: 3.0837 - rpn_class_loss: 0.0869 - rpn_bbox_loss: 1.4498 - mrcnn_class_loss: 0.2744 - mrcnn_bbox_loss: 0.8086 - mrcnn_mask_loss: 0.4641 - val_loss: 2.1729 - val_rpn_class_loss: 0.0503 - val_rpn_bbox_loss: 0.6595 - val_mrcnn_class_loss: 0.3516 - val_mrcnn_bbox_loss: 0.6818 - val_mrcnn_mask_loss: 0.4296
Epoch 2/2
200/200 [==============================] - 833s 4s/step - batch: 99.5000 - size: 8.0000 - loss: 1.9130 - rpn_class_loss: 0.0449 - rpn_bbox_loss: 0.6015 - mrcnn_class_loss: 0.2570 - mrcnn_bbox_loss: 0.5903 - mrcnn_mask_loss: 0.4194 - val_loss: 1.9498 - val_rpn_class_loss: 0.0449 - val_rpn_bbox_loss: 0.5145 - val_mrcnn_class_loss: 0.3335 - val_mrcnn_bbox_loss: 0.6312 - val_mrcnn_mask_loss: 0.4256
Wall time: 27min 12s
history = model.keras_model.history.history
history
{'loss': [3.0836942303180694, 1.9130138206481933],
'rpn_class_loss': [0.08687224984169006, 0.04488518834114075],
'rpn_bbox_loss': [1.4497984647750854, 0.6015039086341858],
'mrcnn_class_loss': [0.2743751108646393, 0.2569710910320282],
'mrcnn_bbox_loss': [0.808597207069397, 0.5902817249298096],
'mrcnn_mask_loss': [0.4640519320964813, 0.419371634721756],
'val_loss': [2.172896957397461, 1.9498254299163817],
'val_rpn_class_loss': [0.050276003777980804, 0.044946618378162384],
'val_rpn_bbox_loss': [0.6595333814620972, 0.5145012140274048],
'val_mrcnn_class_loss': [0.35162219405174255, 0.3335401713848114],
'val_mrcnn_bbox_loss': [0.6818496584892273, 0.6312446594238281],
'val_mrcnn_mask_loss': [0.42961564660072327, 0.425592839717865]}
%%time
new_history_1 = model.train(dataset_train, dataset_val,
learning_rate=LEARNING_RATE,
epochs=6,
layers='all',
augmentation=augmentation)
new_history = model.keras_model.history.history
for k in new_history: history[k] = history[k] + new_history[k]
Starting at epoch 2. LR=0.0006
Checkpoint Path: D://Learrning//great learning//capston Proj//dataset\pneumonia20240320T2057\mask_rcnn_pneumonia_{epoch:04d}.h5
Selecting layers to train
conv1 (Conv2D)
bn_conv1 (BatchNorm)
res2a_branch2a (Conv2D)
bn2a_branch2a (BatchNorm)
res2a_branch2b (Conv2D)
bn2a_branch2b (BatchNorm)
res2a_branch2c (Conv2D)
res2a_branch1 (Conv2D)
bn2a_branch2c (BatchNorm)
bn2a_branch1 (BatchNorm)
res2b_branch2a (Conv2D)
bn2b_branch2a (BatchNorm)
res2b_branch2b (Conv2D)
bn2b_branch2b (BatchNorm)
res2b_branch2c (Conv2D)
bn2b_branch2c (BatchNorm)
res2c_branch2a (Conv2D)
bn2c_branch2a (BatchNorm)
res2c_branch2b (Conv2D)
bn2c_branch2b (BatchNorm)
res2c_branch2c (Conv2D)
bn2c_branch2c (BatchNorm)
res3a_branch2a (Conv2D)
bn3a_branch2a (BatchNorm)
res3a_branch2b (Conv2D)
bn3a_branch2b (BatchNorm)
res3a_branch2c (Conv2D)
res3a_branch1 (Conv2D)
bn3a_branch2c (BatchNorm)
bn3a_branch1 (BatchNorm)
res3b_branch2a (Conv2D)
bn3b_branch2a (BatchNorm)
res3b_branch2b (Conv2D)
bn3b_branch2b (BatchNorm)
res3b_branch2c (Conv2D)
bn3b_branch2c (BatchNorm)
res3c_branch2a (Conv2D)
bn3c_branch2a (BatchNorm)
res3c_branch2b (Conv2D)
bn3c_branch2b (BatchNorm)
res3c_branch2c (Conv2D)
bn3c_branch2c (BatchNorm)
res3d_branch2a (Conv2D)
bn3d_branch2a (BatchNorm)
res3d_branch2b (Conv2D)
bn3d_branch2b (BatchNorm)
res3d_branch2c (Conv2D)
bn3d_branch2c (BatchNorm)
res4a_branch2a (Conv2D)
bn4a_branch2a (BatchNorm)
res4a_branch2b (Conv2D)
bn4a_branch2b (BatchNorm)
res4a_branch2c (Conv2D)
res4a_branch1 (Conv2D)
bn4a_branch2c (BatchNorm)
bn4a_branch1 (BatchNorm)
res4b_branch2a (Conv2D)
bn4b_branch2a (BatchNorm)
res4b_branch2b (Conv2D)
bn4b_branch2b (BatchNorm)
res4b_branch2c (Conv2D)
bn4b_branch2c (BatchNorm)
res4c_branch2a (Conv2D)
bn4c_branch2a (BatchNorm)
res4c_branch2b (Conv2D)
bn4c_branch2b (BatchNorm)
res4c_branch2c (Conv2D)
bn4c_branch2c (BatchNorm)
res4d_branch2a (Conv2D)
bn4d_branch2a (BatchNorm)
res4d_branch2b (Conv2D)
bn4d_branch2b (BatchNorm)
res4d_branch2c (Conv2D)
bn4d_branch2c (BatchNorm)
res4e_branch2a (Conv2D)
bn4e_branch2a (BatchNorm)
res4e_branch2b (Conv2D)
bn4e_branch2b (BatchNorm)
res4e_branch2c (Conv2D)
bn4e_branch2c (BatchNorm)
res4f_branch2a (Conv2D)
bn4f_branch2a (BatchNorm)
res4f_branch2b (Conv2D)
bn4f_branch2b (BatchNorm)
res4f_branch2c (Conv2D)
bn4f_branch2c (BatchNorm)
res5a_branch2a (Conv2D)
bn5a_branch2a (BatchNorm)
res5a_branch2b (Conv2D)
bn5a_branch2b (BatchNorm)
res5a_branch2c (Conv2D)
res5a_branch1 (Conv2D)
bn5a_branch2c (BatchNorm)
bn5a_branch1 (BatchNorm)
res5b_branch2a (Conv2D)
bn5b_branch2a (BatchNorm)
res5b_branch2b (Conv2D)
bn5b_branch2b (BatchNorm)
res5b_branch2c (Conv2D)
bn5b_branch2c (BatchNorm)
res5c_branch2a (Conv2D)
bn5c_branch2a (BatchNorm)
res5c_branch2b (Conv2D)
bn5c_branch2b (BatchNorm)
res5c_branch2c (Conv2D)
bn5c_branch2c (BatchNorm)
fpn_c5p5 (Conv2D)
fpn_c4p4 (Conv2D)
fpn_c3p3 (Conv2D)
fpn_c2p2 (Conv2D)
fpn_p5 (Conv2D)
fpn_p2 (Conv2D)
fpn_p3 (Conv2D)
fpn_p4 (Conv2D)
rpn_model (Functional)
anchors (ConstLayer)
mrcnn_mask_conv1 (TimeDistributed)
mrcnn_mask_bn1 (TimeDistributed)
mrcnn_mask_conv2 (TimeDistributed)
mrcnn_mask_bn2 (TimeDistributed)
mrcnn_class_conv1 (TimeDistributed)
mrcnn_class_bn1 (TimeDistributed)
mrcnn_mask_conv3 (TimeDistributed)
mrcnn_mask_bn3 (TimeDistributed)
mrcnn_class_conv2 (TimeDistributed)
mrcnn_class_bn2 (TimeDistributed)
mrcnn_mask_conv4 (TimeDistributed)
mrcnn_mask_bn4 (TimeDistributed)
mrcnn_bbox_fc (TimeDistributed)
mrcnn_mask_deconv (TimeDistributed)
mrcnn_class_logits (TimeDistributed)
mrcnn_mask (TimeDistributed)
Epoch 3/6
200/200 [==============================] - 1100s 5s/step - batch: 99.5000 - size: 8.0000 - loss: 3.5760 - rpn_class_loss: 0.0395 - rpn_bbox_loss: 0.5168 - mrcnn_class_loss: 0.2560 - mrcnn_bbox_loss: 0.5490 - mrcnn_mask_loss: 0.4268 - val_loss: 3.5847 - val_rpn_class_loss: 0.0397 - val_rpn_bbox_loss: 0.5159 - val_mrcnn_class_loss: 0.2586 - val_mrcnn_bbox_loss: 0.5372 - val_mrcnn_mask_loss: 0.4410
Epoch 4/6
200/200 [==============================] - 1038s 5s/step - batch: 99.5000 - size: 8.0000 - loss: 3.3789 - rpn_class_loss: 0.0336 - rpn_bbox_loss: 0.4762 - mrcnn_class_loss: 0.2387 - mrcnn_bbox_loss: 0.5213 - mrcnn_mask_loss: 0.4196 - val_loss: 3.2764 - val_rpn_class_loss: 0.0321 - val_rpn_bbox_loss: 0.4943 - val_mrcnn_class_loss: 0.2080 - val_mrcnn_bbox_loss: 0.4980 - val_mrcnn_mask_loss: 0.4058
Epoch 5/6
200/200 [==============================] - 1052s 5s/step - batch: 99.5000 - size: 8.0000 - loss: 3.2575 - rpn_class_loss: 0.0313 - rpn_bbox_loss: 0.4623 - mrcnn_class_loss: 0.2222 - mrcnn_bbox_loss: 0.4985 - mrcnn_mask_loss: 0.4143 - val_loss: 3.4192 - val_rpn_class_loss: 0.0312 - val_rpn_bbox_loss: 0.5880 - val_mrcnn_class_loss: 0.2194 - val_mrcnn_bbox_loss: 0.4751 - val_mrcnn_mask_loss: 0.3958
Epoch 6/6
200/200 [==============================] - 1018s 5s/step - batch: 99.5000 - size: 8.0000 - loss: 3.1338 - rpn_class_loss: 0.0293 - rpn_bbox_loss: 0.4317 - mrcnn_class_loss: 0.2176 - mrcnn_bbox_loss: 0.4832 - mrcnn_mask_loss: 0.4050 - val_loss: 3.1681 - val_rpn_class_loss: 0.0278 - val_rpn_bbox_loss: 0.4934 - val_mrcnn_class_loss: 0.1925 - val_mrcnn_bbox_loss: 0.4718 - val_mrcnn_mask_loss: 0.3985
Wall time: 1h 11min 28s
%%time
new_history2 =model.train(dataset_train, dataset_val,
learning_rate=LEARNING_RATE/5,
epochs=2,
layers='all',
augmentation=augmentation)
#for k in new_history: history[k] = history[k] + new_history[k]
Starting at epoch 6. LR=0.00011999999999999999
Checkpoint Path: D://Learrning//great learning//capston Proj//dataset\pneumonia20240320T2057\mask_rcnn_pneumonia_{epoch:04d}.h5
Selecting layers to train
conv1 (Conv2D)
bn_conv1 (BatchNorm)
res2a_branch2a (Conv2D)
bn2a_branch2a (BatchNorm)
res2a_branch2b (Conv2D)
bn2a_branch2b (BatchNorm)
res2a_branch2c (Conv2D)
res2a_branch1 (Conv2D)
bn2a_branch2c (BatchNorm)
bn2a_branch1 (BatchNorm)
res2b_branch2a (Conv2D)
bn2b_branch2a (BatchNorm)
res2b_branch2b (Conv2D)
bn2b_branch2b (BatchNorm)
res2b_branch2c (Conv2D)
bn2b_branch2c (BatchNorm)
res2c_branch2a (Conv2D)
bn2c_branch2a (BatchNorm)
res2c_branch2b (Conv2D)
bn2c_branch2b (BatchNorm)
res2c_branch2c (Conv2D)
bn2c_branch2c (BatchNorm)
res3a_branch2a (Conv2D)
bn3a_branch2a (BatchNorm)
res3a_branch2b (Conv2D)
bn3a_branch2b (BatchNorm)
res3a_branch2c (Conv2D)
res3a_branch1 (Conv2D)
bn3a_branch2c (BatchNorm)
bn3a_branch1 (BatchNorm)
res3b_branch2a (Conv2D)
bn3b_branch2a (BatchNorm)
res3b_branch2b (Conv2D)
bn3b_branch2b (BatchNorm)
res3b_branch2c (Conv2D)
bn3b_branch2c (BatchNorm)
res3c_branch2a (Conv2D)
bn3c_branch2a (BatchNorm)
res3c_branch2b (Conv2D)
bn3c_branch2b (BatchNorm)
res3c_branch2c (Conv2D)
bn3c_branch2c (BatchNorm)
res3d_branch2a (Conv2D)
bn3d_branch2a (BatchNorm)
res3d_branch2b (Conv2D)
bn3d_branch2b (BatchNorm)
res3d_branch2c (Conv2D)
bn3d_branch2c (BatchNorm)
res4a_branch2a (Conv2D)
bn4a_branch2a (BatchNorm)
res4a_branch2b (Conv2D)
bn4a_branch2b (BatchNorm)
res4a_branch2c (Conv2D)
res4a_branch1 (Conv2D)
bn4a_branch2c (BatchNorm)
bn4a_branch1 (BatchNorm)
res4b_branch2a (Conv2D)
bn4b_branch2a (BatchNorm)
res4b_branch2b (Conv2D)
bn4b_branch2b (BatchNorm)
res4b_branch2c (Conv2D)
bn4b_branch2c (BatchNorm)
res4c_branch2a (Conv2D)
bn4c_branch2a (BatchNorm)
res4c_branch2b (Conv2D)
bn4c_branch2b (BatchNorm)
res4c_branch2c (Conv2D)
bn4c_branch2c (BatchNorm)
res4d_branch2a (Conv2D)
bn4d_branch2a (BatchNorm)
res4d_branch2b (Conv2D)
bn4d_branch2b (BatchNorm)
res4d_branch2c (Conv2D)
bn4d_branch2c (BatchNorm)
res4e_branch2a (Conv2D)
bn4e_branch2a (BatchNorm)
res4e_branch2b (Conv2D)
bn4e_branch2b (BatchNorm)
res4e_branch2c (Conv2D)
bn4e_branch2c (BatchNorm)
res4f_branch2a (Conv2D)
bn4f_branch2a (BatchNorm)
res4f_branch2b (Conv2D)
bn4f_branch2b (BatchNorm)
res4f_branch2c (Conv2D)
bn4f_branch2c (BatchNorm)
res5a_branch2a (Conv2D)
bn5a_branch2a (BatchNorm)
res5a_branch2b (Conv2D)
bn5a_branch2b (BatchNorm)
res5a_branch2c (Conv2D)
res5a_branch1 (Conv2D)
bn5a_branch2c (BatchNorm)
bn5a_branch1 (BatchNorm)
res5b_branch2a (Conv2D)
bn5b_branch2a (BatchNorm)
res5b_branch2b (Conv2D)
bn5b_branch2b (BatchNorm)
res5b_branch2c (Conv2D)
bn5b_branch2c (BatchNorm)
res5c_branch2a (Conv2D)
bn5c_branch2a (BatchNorm)
res5c_branch2b (Conv2D)
bn5c_branch2b (BatchNorm)
res5c_branch2c (Conv2D)
bn5c_branch2c (BatchNorm)
fpn_c5p5 (Conv2D)
fpn_c4p4 (Conv2D)
fpn_c3p3 (Conv2D)
fpn_c2p2 (Conv2D)
fpn_p5 (Conv2D)
fpn_p2 (Conv2D)
fpn_p3 (Conv2D)
fpn_p4 (Conv2D)
rpn_model (Functional)
anchors (ConstLayer)
mrcnn_mask_conv1 (TimeDistributed)
mrcnn_mask_bn1 (TimeDistributed)
mrcnn_mask_conv2 (TimeDistributed)
mrcnn_mask_bn2 (TimeDistributed)
mrcnn_class_conv1 (TimeDistributed)
mrcnn_class_bn1 (TimeDistributed)
mrcnn_mask_conv3 (TimeDistributed)
mrcnn_mask_bn3 (TimeDistributed)
mrcnn_class_conv2 (TimeDistributed)
mrcnn_class_bn2 (TimeDistributed)
mrcnn_mask_conv4 (TimeDistributed)
mrcnn_mask_bn4 (TimeDistributed)
mrcnn_bbox_fc (TimeDistributed)
mrcnn_mask_deconv (TimeDistributed)
mrcnn_class_logits (TimeDistributed)
mrcnn_mask (TimeDistributed)
Wall time: 2min 20s
new_history
{'loss': [3.576004112958908,
3.3788726317882536,
3.25745086312294,
3.1337632393836974],
'rpn_class_loss': [0.039470549672842026,
0.0335860475897789,
0.03133852779865265,
0.02932998165488243],
'rpn_bbox_loss': [0.5167896151542664,
0.4761902093887329,
0.46232137084007263,
0.4317075312137604],
'mrcnn_class_loss': [0.2560274600982666,
0.23874549567699432,
0.22220641374588013,
0.21762388944625854],
'mrcnn_bbox_loss': [0.5489606857299805,
0.5212969779968262,
0.49854832887649536,
0.48319369554519653],
'mrcnn_mask_loss': [0.42675384879112244,
0.41961753368377686,
0.4143105447292328,
0.40502655506134033],
'val_loss': [3.5846843242645265,
3.2763502836227416,
3.419161319732666,
3.1680942296981813],
'val_rpn_class_loss': [0.03969850018620491,
0.03210816532373428,
0.031239649280905724,
0.027838075533509254],
'val_rpn_bbox_loss': [0.5158947110176086,
0.4943275451660156,
0.5879630446434021,
0.49341249465942383],
'val_mrcnn_class_loss': [0.25856396555900574,
0.20798993110656738,
0.2194116860628128,
0.19248999655246735],
'val_mrcnn_bbox_loss': [0.5371931195259094,
0.4979827404022217,
0.47511887550354004,
0.4717771112918854],
'val_mrcnn_mask_loss': [0.4409918189048767,
0.4057668149471283,
0.39584752917289734,
0.39852941036224365]}
epochs = range(1,len(next(iter(history.values())))+1)
pd.DataFrame(history, index=epochs)
| loss | rpn_class_loss | rpn_bbox_loss | mrcnn_class_loss | mrcnn_bbox_loss | mrcnn_mask_loss | val_loss | val_rpn_class_loss | val_rpn_bbox_loss | val_mrcnn_class_loss | val_mrcnn_bbox_loss | val_mrcnn_mask_loss | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 3.083694 | 0.086872 | 1.449798 | 0.274375 | 0.808597 | 0.464052 | 2.172897 | 0.050276 | 0.659533 | 0.351622 | 0.681850 | 0.429616 |
| 2 | 1.913014 | 0.044885 | 0.601504 | 0.256971 | 0.590282 | 0.419372 | 1.949825 | 0.044947 | 0.514501 | 0.333540 | 0.631245 | 0.425593 |
| 3 | 3.576004 | 0.039471 | 0.516790 | 0.256027 | 0.548961 | 0.426754 | 3.584684 | 0.039699 | 0.515895 | 0.258564 | 0.537193 | 0.440992 |
| 4 | 3.378873 | 0.033586 | 0.476190 | 0.238745 | 0.521297 | 0.419618 | 3.276350 | 0.032108 | 0.494328 | 0.207990 | 0.497983 | 0.405767 |
| 5 | 3.257451 | 0.031339 | 0.462321 | 0.222206 | 0.498548 | 0.414311 | 3.419161 | 0.031240 | 0.587963 | 0.219412 | 0.475119 | 0.395848 |
| 6 | 3.133763 | 0.029330 | 0.431708 | 0.217624 | 0.483194 | 0.405027 | 3.168094 | 0.027838 | 0.493412 | 0.192490 | 0.471777 | 0.398529 |
plt.figure(figsize=(17,5))
plt.subplot(131)
plt.plot(epochs, history["loss"], label="Train loss")
plt.plot(epochs, history["val_loss"], label="Valid loss")
plt.legend()
plt.subplot(132)
plt.plot(epochs, history["mrcnn_class_loss"], label="Train class ce")
plt.plot(epochs, history["val_mrcnn_class_loss"], label="Valid class ce")
plt.legend()
plt.subplot(133)
plt.plot(epochs, history["mrcnn_bbox_loss"], label="Train box loss")
plt.plot(epochs, history["val_mrcnn_bbox_loss"], label="Valid box loss")
plt.legend()
plt.show()
best_epoch = np.argmin(history["val_loss"])
print("Best Epoch:", best_epoch + 1, history["val_loss"][best_epoch])
Best Epoch: 2 1.9498254299163817
# select trained model
dir_names = next(os.walk(model.model_dir))[1]
key = config.NAME.lower()
dir_names = filter(lambda f: f.startswith(key), dir_names)
dir_names = sorted(dir_names)
if not dir_names:
import errno
raise FileNotFoundError(
errno.ENOENT,
"Could not find model directory under {}".format(self.model_dir))
fps = []
# Pick last directory
for d in dir_names:
dir_name = os.path.join(model.model_dir, d)
# Find the last checkpoint
checkpoints = next(os.walk(dir_name))[2]
checkpoints = filter(lambda f: f.startswith("mask_rcnn"), checkpoints)
checkpoints = sorted(checkpoints)
if not checkpoints:
print('No weight files in {}'.format(dir_name))
else:
checkpoint = os.path.join(dir_name, checkpoints[best_epoch])
fps.append(checkpoint)
model_path = sorted(fps)[-1]
print('Found model {}'.format(model_path))
No weight files in D://Learrning//great learning//capston Proj//dataset\pneumonia20240317T1642 No weight files in D://Learrning//great learning//capston Proj//dataset\pneumonia20240317T1838 Found model D://Learrning//great learning//capston Proj//dataset\pneumonia20240320T2057\mask_rcnn_pneumonia_0002.h5
class InferenceConfig(DetectorConfig):
GPU_COUNT = 1
IMAGES_PER_GPU = 1
inference_config = InferenceConfig()
# Recreate the model in inference mode
model = modellib.MaskRCNN(mode='inference',
config=inference_config,
model_dir=ROOT_DIR)
# Load trained weights (fill in path to trained weights here)
assert model_path != "", "Provide path to trained weights"
print("Loading weights from ", model_path)
model.load_weights(model_path, by_name=True)
WARNING:tensorflow:From C:\AnacondaPython\envs\tensorflow\lib\site-packages\tensorflow\python\util\deprecation.py:616: calling map_fn_v2 (from tensorflow.python.ops.map_fn) with dtype is deprecated and will be removed in a future version. Instructions for updating: Use fn_output_signature instead Loading weights from D://Learrning//great learning//capston Proj//dataset\pneumonia20240320T2057\mask_rcnn_pneumonia_0002.h5 Re-starting from epoch 2
# set color for class
def get_colors_for_class_ids(class_ids):
colors = []
for class_id in class_ids:
if class_id == 1:
colors.append((.941, .204, .204))
return colors
Note that we trained only one epoch for demonstration purposes ONLY. You might be able to improve performance running more epochs.
# Show few example of ground truth vs. predictions on the validation dataset
dataset = dataset_val
fig = plt.figure(figsize=(5,5))
for i in range(3):
image_id = random.choice(dataset.image_ids)
original_image, image_meta, gt_class_id, gt_bbox, gt_mask =\
modellib.load_image_gt(dataset_val, inference_config,
image_id)
# print(original_image.shape)
# plt.subplot(3, 2, 2*i + 1)
visualize.display_instances(original_image, gt_bbox, gt_mask, gt_class_id,
dataset.class_names,
colors=get_colors_for_class_ids(gt_class_id))
# plt.subplot(3, 2, 2*i + 2)
results = model.detect([original_image]) #, verbose=1)
r = results[0]
visualize.display_instances(original_image, r['rois'], r['masks'], r['class_ids'],
dataset.class_names, r['scores'],
colors=get_colors_for_class_ids(r['class_ids']))
(128, 128, 3) *** No instances to display ***
<Figure size 360x360 with 0 Axes>
(128, 128, 3) *** No instances to display ***
(128, 128, 3) *** No instances to display ***
test_image_fps = get_dicom_fps(test_dicom_dir)
# Make predictions on test images, write out sample submission
def predict(image_fps, filepath='submission_final.csv', min_conf=0.95):
# assume square image
resize_factor = ORIG_SIZE / config.IMAGE_SHAPE[0]
#resize_factor = ORIG_SIZE
with open(filepath, 'w') as file:
file.write("patientId,PredictionString\n")
for image_id in tqdm(image_fps):
ds = pydicom.read_file(image_id)
image = ds.pixel_array
# If grayscale. Convert to RGB for consistency.
if len(image.shape) != 3 or image.shape[2] != 3:
image = np.stack((image,) * 3, -1)
image, window, scale, padding, crop = utils.resize_image(
image,
min_dim=config.IMAGE_MIN_DIM,
min_scale=config.IMAGE_MIN_SCALE,
max_dim=config.IMAGE_MAX_DIM,
mode=config.IMAGE_RESIZE_MODE)
patient_id = os.path.splitext(os.path.basename(image_id))[0]
results = model.detect([image])
r = results[0]
out_str = ""
out_str += patient_id
out_str += ","
assert( len(r['rois']) == len(r['class_ids']) == len(r['scores']) )
if len(r['rois']) == 0:
pass
else:
num_instances = len(r['rois'])
for i in range(num_instances):
if r['scores'][i] > min_conf:
out_str += ' '
out_str += str(round(r['scores'][i], 2))
out_str += ' '
# x1, y1, width, height
x1 = r['rois'][i][1]
y1 = r['rois'][i][0]
width = r['rois'][i][3] - x1
height = r['rois'][i][2] - y1
bboxes_str = "{} {} {} {}".format(x1*resize_factor, y1*resize_factor, \
width*resize_factor, height*resize_factor)
out_str += bboxes_str
file.write(out_str+"\n")
import pickle
# Pickle the model to a file
with open('rcnnmodelfnl1.pkl', 'wb') as f:
pickle.dump(model, f)
INFO:tensorflow:Assets written to: ram://aabe065f-874a-44f6-98f5-75b15b6be25b/assets
submission_fp = os.path.join(ROOT_DIR, 'submissionfinal1.csv')
predict(test_image_fps, filepath=submission_fp)
print(submission_fp)
100%|██████████████████████████████████████████████████████████████████████████████| 3000/3000 [11:22<00:00, 4.40it/s]
D://Learrning//great learning//capston Proj//dataset\submissionfinal1.csv
# show a few test image detection example
def visualize():
image_id = random.choice(test_image_fps)
ds = pydicom.read_file(image_id)
# original image
image = ds.pixel_array
# assume square image
resize_factor = ORIG_SIZE / config.IMAGE_SHAPE[0]
# If grayscale. Convert to RGB for consistency.
if len(image.shape) != 3 or image.shape[2] != 3:
image = np.stack((image,) * 3, -1)
resized_image, window, scale, padding, crop = utils.resize_image(
image,
min_dim=config.IMAGE_MIN_DIM,
min_scale=config.IMAGE_MIN_SCALE,
max_dim=config.IMAGE_MAX_DIM,
mode=config.IMAGE_RESIZE_MODE)
patient_id = os.path.splitext(os.path.basename(image_id))[0]
print(patient_id)
results = model.detect([resized_image])
r = results[0]
for bbox in r['rois']:
print(bbox)
x1 = int(bbox[1] * resize_factor)
y1 = int(bbox[0] * resize_factor)
x2 = int(bbox[3] * resize_factor)
y2 = int(bbox[2] * resize_factor)
cv2.rectangle(image, (x1,y1), (x2,y2), (77, 255, 9), 3, 1)
width = x2 - x1
height = y2 - y1
print("x {} y {} h {} w {}".format(x1, y1, width, height))
plt.figure()
plt.imshow(image, cmap=plt.cm.gist_gray)
visualize()
visualize()
visualize()
visualize()
2bb5fb3e-0a7d-42c1-bec3-bf86f6fe4029 [ 81 0 107 65] x 0 y 648 h 520 w 208 [19 0 21 1] x 0 y 152 h 8 w 16 [69 0 79 14] x 0 y 552 h 112 w 80 14cf8563-6ed2-4458-8659-cd2618a74f7e [ 2 0 15 2] x 0 y 16 h 16 w 104 [18 0 19 1] x 0 y 144 h 8 w 8 [79 0 87 24] x 0 y 632 h 192 w 64 1ead85b0-dada-4d3e-8a39-3989aaba75c2 [46 0 55 92] x 0 y 368 h 736 w 72 [ 62 0 67 128] x 0 y 496 h 1024 w 40 [ 74 0 76 128] x 0 y 592 h 1024 w 16 2838eabe-5ddc-4ddd-8934-91e362d10d18 [107 0 109 128] x 0 y 856 h 1024 w 16 [105 0 108 128] x 0 y 840 h 1024 w 24 [82 0 85 63] x 0 y 656 h 504 w 24
%pip install ultralytics
Collecting ultralytics
Using cached ultralytics-8.1.30-py3-none-any.whl (722 kB)
Requirement already satisfied: matplotlib>=3.3.0 in c:\anacondapython\lib\site-packages (from ultralytics) (3.4.2)
Collecting tqdm>=4.64.0
Downloading tqdm-4.66.2-py3-none-any.whl (78 kB)
Collecting py-cpuinfo
Using cached py_cpuinfo-9.0.0-py3-none-any.whl (22 kB)
Requirement already satisfied: psutil in c:\anacondapython\lib\site-packages (from ultralytics) (5.7.2)
Requirement already satisfied: torch>=1.8.0 in c:\anacondapython\lib\site-packages (from ultralytics) (2.2.1+cu121)
Requirement already satisfied: pillow>=7.1.2 in c:\anacondapython\lib\site-packages (from ultralytics) (9.0.1)
Requirement already satisfied: pyyaml>=5.3.1 in c:\anacondapython\lib\site-packages (from ultralytics) (6.0)
Collecting thop>=0.1.1
Using cached thop-0.1.1.post2209072238-py3-none-any.whl (15 kB)
Requirement already satisfied: requests>=2.23.0 in c:\anacondapython\lib\site-packages (from ultralytics) (2.27.1)
Requirement already satisfied: pandas>=1.1.4 in c:\anacondapython\lib\site-packages (from ultralytics) (1.4.1)
Requirement already satisfied: scipy>=1.4.1 in c:\anacondapython\lib\site-packages (from ultralytics) (1.7.3)
Requirement already satisfied: seaborn>=0.11.0 in c:\anacondapython\lib\site-packages (from ultralytics) (0.11.2)
Requirement already satisfied: torchvision>=0.9.0 in c:\anacondapython\lib\site-packages (from ultralytics) (0.17.1+cu121)
Requirement already satisfied: opencv-python>=4.6.0 in c:\anacondapython\lib\site-packages (from ultralytics) (4.8.1.78)
Requirement already satisfied: kiwisolver>=1.0.1 in c:\anacondapython\lib\site-packages (from matplotlib>=3.3.0->ultralytics) (1.3.0)
Requirement already satisfied: python-dateutil>=2.7 in c:\anacondapython\lib\site-packages (from matplotlib>=3.3.0->ultralytics) (2.8.1)
Requirement already satisfied: pyparsing>=2.2.1 in c:\anacondapython\lib\site-packages (from matplotlib>=3.3.0->ultralytics) (2.4.7)
Requirement already satisfied: numpy>=1.16 in c:\anacondapython\lib\site-packages (from matplotlib>=3.3.0->ultralytics) (1.22.2)
Requirement already satisfied: cycler>=0.10 in c:\anacondapython\lib\site-packages (from matplotlib>=3.3.0->ultralytics) (0.10.0)
Requirement already satisfied: colorama; platform_system == "Windows" in c:\anacondapython\lib\site-packages (from tqdm>=4.64.0->ultralytics) (0.4.6)
Requirement already satisfied: typing-extensions>=4.8.0 in c:\anacondapython\lib\site-packages (from torch>=1.8.0->ultralytics) (4.9.0)
Requirement already satisfied: jinja2 in c:\anacondapython\lib\site-packages (from torch>=1.8.0->ultralytics) (3.1.2)
Requirement already satisfied: sympy in c:\anacondapython\lib\site-packages (from torch>=1.8.0->ultralytics) (1.6.2)
Requirement already satisfied: fsspec in c:\anacondapython\lib\site-packages (from torch>=1.8.0->ultralytics) (0.8.3)
Requirement already satisfied: filelock in c:\anacondapython\lib\site-packages (from torch>=1.8.0->ultralytics) (3.0.12)
Requirement already satisfied: networkx in c:\anacondapython\lib\site-packages (from torch>=1.8.0->ultralytics) (2.5)
Requirement already satisfied: urllib3<1.27,>=1.21.1 in c:\anacondapython\lib\site-packages (from requests>=2.23.0->ultralytics) (1.26.8)
Requirement already satisfied: charset-normalizer~=2.0.0; python_version >= "3" in c:\anacondapython\lib\site-packages (from requests>=2.23.0->ultralytics) (2.0.12)
Requirement already satisfied: idna<4,>=2.5; python_version >= "3" in c:\anacondapython\lib\site-packages (from requests>=2.23.0->ultralytics) (2.10)
Requirement already satisfied: certifi>=2017.4.17 in c:\anacondapython\lib\site-packages (from requests>=2.23.0->ultralytics) (2023.11.17)
Requirement already satisfied: pytz>=2020.1 in c:\anacondapython\lib\site-packages (from pandas>=1.1.4->ultralytics) (2020.1)
Requirement already satisfied: six>=1.5 in c:\anacondapython\lib\site-packages (from python-dateutil>=2.7->matplotlib>=3.3.0->ultralytics) (1.15.0)
Requirement already satisfied: MarkupSafe>=2.0 in c:\anacondapython\lib\site-packages (from jinja2->torch>=1.8.0->ultralytics) (2.1.1)
Requirement already satisfied: mpmath>=0.19 in c:\anacondapython\lib\site-packages (from sympy->torch>=1.8.0->ultralytics) (1.1.0)
Requirement already satisfied: decorator>=4.3.0 in c:\anacondapython\lib\site-packages (from networkx->torch>=1.8.0->ultralytics) (4.4.2)
Installing collected packages: tqdm, py-cpuinfo, thop, ultralytics
Attempting uninstall: tqdm
Found existing installation: tqdm 4.50.2
Uninstalling tqdm-4.50.2:
Successfully uninstalled tqdm-4.50.2
Successfully installed py-cpuinfo-9.0.0 thop-0.1.1.post2209072238 tqdm-4.66.2 ultralytics-8.1.30
Note: you may need to restart the kernel to use updated packages.
import numpy as np
import pandas as pd
import os
import random
import shutil
import cv2
import pydicom
from PIL import Image
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from tqdm import tqdm
import torch
from ultralytics import YOLO
np.random.seed(1111)
torch.cuda.is_available()
True
CSV_FILE = 'stage_2_train_labels.csv'
TRAIN_SRC_DIR = 'train_images/stage_2_train_images/'
TEST_SRC_DIR = 'test_images/stage_2_test_images/'
DATASET_DIR = 'D://Learrning//great learning//capston Proj//dataset//yolo//'
TEST_IMG_DIR = 'D://Learrning//great learning//capston Proj//dataset///test_images_yolo/'
os.mkdir(DATASET_DIR)
os.mkdir(DATASET_DIR + 'images/')
os.mkdir(DATASET_DIR + 'images/train/')
os.mkdir(DATASET_DIR + 'images/val/')
os.mkdir(DATASET_DIR + 'images/test/')
os.mkdir(DATASET_DIR + 'labels/')
os.mkdir(DATASET_DIR + 'labels/train/')
os.mkdir(DATASET_DIR + 'labels/val/')
os.mkdir(DATASET_DIR + 'labels/test/')
os.mkdir(TEST_IMG_DIR)
annotations = pd.read_csv(CSV_FILE)
print(annotations.info())
annotations.head()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 30227 entries, 0 to 30226 Data columns (total 6 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 patientId 30227 non-null object 1 x 9555 non-null float64 2 y 9555 non-null float64 3 width 9555 non-null float64 4 height 9555 non-null float64 5 Target 30227 non-null int64 dtypes: float64(4), int64(1), object(1) memory usage: 1.4+ MB None
| patientId | x | y | width | height | Target | |
|---|---|---|---|---|---|---|
| 0 | 0004cfab-14fd-4e49-80ba-63a80b6bddd6 | NaN | NaN | NaN | NaN | 0 |
| 1 | 00313ee0-9eaa-42f4-b0ab-c148ed3241cd | NaN | NaN | NaN | NaN | 0 |
| 2 | 00322d4d-1c29-4943-afc9-b6754be640eb | NaN | NaN | NaN | NaN | 0 |
| 3 | 003d8fa0-6bf1-40ed-b54c-ac657f8495c5 | NaN | NaN | NaN | NaN | 0 |
| 4 | 00436515-870c-4b36-a041-de91049b9ab4 | 264.0 | 152.0 | 213.0 | 379.0 | 1 |
positive_annotations = annotations[annotations.Target == 1]
negative_annotations = annotations[annotations.Target == 0]
print(positive_annotations['patientId'].drop_duplicates().shape[0])
print(negative_annotations['patientId'].drop_duplicates().shape[0])
print(negative_annotations['patientId'].shape[0])
negative_sample = negative_annotations.sample(600)
negative_sample['patientId'].shape[0]
annotations = pd.concat([positive_annotations, negative_sample])
print(annotations.shape)
annotations.head()
6012 20672 20672 (10155, 6)
| patientId | x | y | width | height | Target | |
|---|---|---|---|---|---|---|
| 4 | 00436515-870c-4b36-a041-de91049b9ab4 | 264.0 | 152.0 | 213.0 | 379.0 | 1 |
| 5 | 00436515-870c-4b36-a041-de91049b9ab4 | 562.0 | 152.0 | 256.0 | 453.0 | 1 |
| 8 | 00704310-78a8-4b38-8475-49f4573b2dbb | 323.0 | 577.0 | 160.0 | 104.0 | 1 |
| 9 | 00704310-78a8-4b38-8475-49f4573b2dbb | 695.0 | 575.0 | 162.0 | 137.0 | 1 |
| 14 | 00aecb01-a116-45a2-956c-08d2fa55433f | 288.0 | 322.0 | 94.0 | 135.0 | 1 |
patient_id_series = annotations.patientId.drop_duplicates()
print('Number of images:', patient_id_series.size)
train_series, val_series = train_test_split(patient_id_series, test_size=0.1, random_state=42)
print('Train set number:', len(train_series))
print('Validation set number:', len(val_series))
Number of images: 6612 Train set number: 5950 Validation set number: 662
for patient_id in tqdm(train_series):
src_path = TRAIN_SRC_DIR + patient_id + '.dcm'
dcm_data = pydicom.dcmread(src_path)
image_array = dcm_data.pixel_array
image = Image.fromarray(image_array)
image.save(DATASET_DIR + 'images/train/' + patient_id + '.jpg')
print('Images moved to train folder:', len(os.listdir(DATASET_DIR + 'images/train/')))
for patient_id in tqdm(val_series):
src_path = TRAIN_SRC_DIR + patient_id + '.dcm'
dcm_data = pydicom.dcmread(src_path)
image_array = dcm_data.pixel_array
image = Image.fromarray(image_array)
image.save(DATASET_DIR + 'images/val/' + patient_id + '.jpg')
print('Images moved to val folder:', len(os.listdir(DATASET_DIR + 'images/val/')))
100%|██████████████████████████████████████████████████████████████████████████████| 5950/5950 [01:03<00:00, 93.52it/s]
Images moved to train folder: 5950
100%|████████████████████████████████████████████████████████████████████████████████| 662/662 [00:06<00:00, 98.12it/s]
Images moved to val folder: 662
def translate_bbox(bbox):
img_size = 1024 # rsna defualt image size
top_left_x = bbox[0]
top_left_y = bbox[1]
absolute_w = bbox[2]
absolute_h = bbox[3]
relative_w = absolute_w / img_size
relative_h = absolute_h / img_size
relative_x = top_left_x / img_size + relative_w / 2
relative_y = top_left_y / img_size + relative_h / 2
return relative_x, relative_y, relative_w, relative_h
def revert_bbox(rx, ry, rw, rh):
img_size = 1024 # rsna defualt image size
x = (rx-rw/2)*img_size
y = (ry-rh/2)*img_size
w = rw*img_size
h = rh*img_size
return x, y, w, h
def save_label(label_dir, patient_id, bbox):
label_fp = os.path.join(label_dir, patient_id + '.txt')
f = open(label_fp, "a")
if (bbox == 'nan').all():
f.close()
return
x, y, w, h = translate_bbox(bbox)
line = f"0 {x} {y} {w} {h}\n"
f.write(line)
f.close()
LABELS_DIR = "./labels_temp/"
os.mkdir(LABELS_DIR)
for row in annotations.values:
if pd.notna(row[1:5]).all():
save_label(LABELS_DIR, row[0], row[1:5])
for patient_id in train_series:
if os.path.isfile(LABELS_DIR + patient_id + '.txt'):
shutil.copy(LABELS_DIR + patient_id + '.txt', DATASET_DIR + 'labels/train/')
for patient_id in val_series:
if os.path.isfile(LABELS_DIR + patient_id + '.txt'):
shutil.copy(LABELS_DIR + patient_id + '.txt', DATASET_DIR + 'labels/val/')
shutil.rmtree(LABELS_DIR)
demo_patient_id = val_series.values[8]
demo_img_path = DATASET_DIR + 'images/val/' + demo_patient_id + '.jpg'
demo_label_path = DATASET_DIR + 'labels/val/' + demo_patient_id + '.txt'
plt.imshow(cv2.imread(demo_img_path))
with open(demo_label_path, "r") as f:
for line in f:
print(line)
class_id, rx, ry, rw, rh = list(map(float, line.strip().split()))
x, y, w, h = revert_bbox(rx, ry, rw, rh)
plt.plot([x, x, x+w, x+w, x], [y, y+h, y+h, y, y])
0 0.7412109375 0.49658203125 0.162109375 0.0966796875
%%writefile config.yaml
path: 'D://Learrning//great learning//capston Proj//dataset//yolo' # dataset root dir
train: images/train # train images (relative to 'path')
val: images/val # val images (relative to 'path')
# Classes
names:
0: pneumonia
Writing config.yaml
model = YOLO('yolov8l.pt') # yaml
model.to('cuda:0')
YOLO(
(model): DetectionModel(
(model): Sequential(
(0): Conv(
(conv): Conv2d(3, 64, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
(bn): BatchNorm2d(64, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(1): Conv(
(conv): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
(bn): BatchNorm2d(128, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(2): C2f(
(cv1): Conv(
(conv): Conv2d(128, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn): BatchNorm2d(128, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(cv2): Conv(
(conv): Conv2d(320, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn): BatchNorm2d(128, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(m): ModuleList(
(0-2): 3 x Bottleneck(
(cv1): Conv(
(conv): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(64, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(cv2): Conv(
(conv): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(64, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
)
)
)
(3): Conv(
(conv): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
(bn): BatchNorm2d(256, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(4): C2f(
(cv1): Conv(
(conv): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn): BatchNorm2d(256, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(cv2): Conv(
(conv): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn): BatchNorm2d(256, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(m): ModuleList(
(0-5): 6 x Bottleneck(
(cv1): Conv(
(conv): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(128, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(cv2): Conv(
(conv): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(128, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
)
)
)
(5): Conv(
(conv): Conv2d(256, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
(bn): BatchNorm2d(512, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(6): C2f(
(cv1): Conv(
(conv): Conv2d(512, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn): BatchNorm2d(512, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(cv2): Conv(
(conv): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn): BatchNorm2d(512, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(m): ModuleList(
(0-5): 6 x Bottleneck(
(cv1): Conv(
(conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(256, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(cv2): Conv(
(conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(256, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
)
)
)
(7): Conv(
(conv): Conv2d(512, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
(bn): BatchNorm2d(512, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(8): C2f(
(cv1): Conv(
(conv): Conv2d(512, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn): BatchNorm2d(512, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(cv2): Conv(
(conv): Conv2d(1280, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn): BatchNorm2d(512, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(m): ModuleList(
(0-2): 3 x Bottleneck(
(cv1): Conv(
(conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(256, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(cv2): Conv(
(conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(256, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
)
)
)
(9): SPPF(
(cv1): Conv(
(conv): Conv2d(512, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn): BatchNorm2d(256, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(cv2): Conv(
(conv): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn): BatchNorm2d(512, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(m): MaxPool2d(kernel_size=5, stride=1, padding=2, dilation=1, ceil_mode=False)
)
(10): Upsample(scale_factor=2.0, mode='nearest')
(11): Concat()
(12): C2f(
(cv1): Conv(
(conv): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn): BatchNorm2d(512, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(cv2): Conv(
(conv): Conv2d(1280, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn): BatchNorm2d(512, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(m): ModuleList(
(0-2): 3 x Bottleneck(
(cv1): Conv(
(conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(256, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(cv2): Conv(
(conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(256, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
)
)
)
(13): Upsample(scale_factor=2.0, mode='nearest')
(14): Concat()
(15): C2f(
(cv1): Conv(
(conv): Conv2d(768, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn): BatchNorm2d(256, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(cv2): Conv(
(conv): Conv2d(640, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn): BatchNorm2d(256, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(m): ModuleList(
(0-2): 3 x Bottleneck(
(cv1): Conv(
(conv): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(128, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(cv2): Conv(
(conv): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(128, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
)
)
)
(16): Conv(
(conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
(bn): BatchNorm2d(256, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(17): Concat()
(18): C2f(
(cv1): Conv(
(conv): Conv2d(768, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn): BatchNorm2d(512, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(cv2): Conv(
(conv): Conv2d(1280, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn): BatchNorm2d(512, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(m): ModuleList(
(0-2): 3 x Bottleneck(
(cv1): Conv(
(conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(256, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(cv2): Conv(
(conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(256, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
)
)
)
(19): Conv(
(conv): Conv2d(512, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
(bn): BatchNorm2d(512, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(20): Concat()
(21): C2f(
(cv1): Conv(
(conv): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn): BatchNorm2d(512, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(cv2): Conv(
(conv): Conv2d(1280, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
(bn): BatchNorm2d(512, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(m): ModuleList(
(0-2): 3 x Bottleneck(
(cv1): Conv(
(conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(256, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(cv2): Conv(
(conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(256, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
)
)
)
(22): Detect(
(cv2): ModuleList(
(0): Sequential(
(0): Conv(
(conv): Conv2d(256, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(64, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(1): Conv(
(conv): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(64, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(2): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1))
)
(1-2): 2 x Sequential(
(0): Conv(
(conv): Conv2d(512, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(64, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(1): Conv(
(conv): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(64, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(2): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1))
)
)
(cv3): ModuleList(
(0): Sequential(
(0): Conv(
(conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(256, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(1): Conv(
(conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(256, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(2): Conv2d(256, 80, kernel_size=(1, 1), stride=(1, 1))
)
(1-2): 2 x Sequential(
(0): Conv(
(conv): Conv2d(512, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(256, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(1): Conv(
(conv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn): BatchNorm2d(256, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
(act): SiLU(inplace=True)
)
(2): Conv2d(256, 80, kernel_size=(1, 1), stride=(1, 1))
)
)
(dfl): DFL(
(conv): Conv2d(16, 1, kernel_size=(1, 1), stride=(1, 1), bias=False)
)
)
)
)
)
results = model.train(data='config.yaml', epochs=10,device=0)
Ultralytics YOLOv8.1.30 🚀 Python-3.8.5 torch-2.2.1+cu121 CUDA:0 (NVIDIA GeForce RTX 2060, 6144MiB) engine\trainer: task=detect, mode=train, model=yolov8l.pt, data=config.yaml, epochs=10, time=None, patience=100, batch=16, imgsz=640, save=True, save_period=-1, cache=False, device=0, workers=8, project=None, name=train2, exist_ok=False, pretrained=True, optimizer=auto, verbose=True, seed=0, deterministic=True, single_cls=False, rect=False, cos_lr=False, close_mosaic=10, resume=False, amp=True, fraction=1.0, profile=False, freeze=None, multi_scale=False, overlap_mask=True, mask_ratio=4, dropout=0.0, val=True, split=val, save_json=False, save_hybrid=False, conf=None, iou=0.7, max_det=300, half=False, dnn=False, plots=True, source=None, vid_stride=1, stream_buffer=False, visualize=False, augment=False, agnostic_nms=False, classes=None, retina_masks=False, embed=None, show=False, save_frames=False, save_txt=False, save_conf=False, save_crop=False, show_labels=True, show_conf=True, show_boxes=True, line_width=None, format=torchscript, keras=False, optimize=False, int8=False, dynamic=False, simplify=False, opset=None, workspace=4, nms=False, lr0=0.01, lrf=0.01, momentum=0.937, weight_decay=0.0005, warmup_epochs=3.0, warmup_momentum=0.8, warmup_bias_lr=0.1, box=7.5, cls=0.5, dfl=1.5, pose=12.0, kobj=1.0, label_smoothing=0.0, nbs=64, hsv_h=0.015, hsv_s=0.7, hsv_v=0.4, degrees=0.0, translate=0.1, scale=0.5, shear=0.0, perspective=0.0, flipud=0.0, fliplr=0.5, mosaic=1.0, mixup=0.0, copy_paste=0.0, auto_augment=randaugment, erasing=0.4, crop_fraction=1.0, cfg=None, tracker=botsort.yaml, save_dir=runs\detect\train2 Overriding model.yaml nc=80 with nc=1 from n params module arguments 0 -1 1 1856 ultralytics.nn.modules.conv.Conv [3, 64, 3, 2] 1 -1 1 73984 ultralytics.nn.modules.conv.Conv [64, 128, 3, 2] 2 -1 3 279808 ultralytics.nn.modules.block.C2f [128, 128, 3, True] 3 -1 1 295424 ultralytics.nn.modules.conv.Conv [128, 256, 3, 2] 4 -1 6 2101248 ultralytics.nn.modules.block.C2f [256, 256, 6, True] 5 -1 1 1180672 ultralytics.nn.modules.conv.Conv [256, 512, 3, 2] 6 -1 6 8396800 ultralytics.nn.modules.block.C2f [512, 512, 6, True] 7 -1 1 2360320 ultralytics.nn.modules.conv.Conv [512, 512, 3, 2] 8 -1 3 4461568 ultralytics.nn.modules.block.C2f [512, 512, 3, True] 9 -1 1 656896 ultralytics.nn.modules.block.SPPF [512, 512, 5] 10 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, 'nearest'] 11 [-1, 6] 1 0 ultralytics.nn.modules.conv.Concat [1] 12 -1 3 4723712 ultralytics.nn.modules.block.C2f [1024, 512, 3] 13 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, 'nearest'] 14 [-1, 4] 1 0 ultralytics.nn.modules.conv.Concat [1] 15 -1 3 1247744 ultralytics.nn.modules.block.C2f [768, 256, 3] 16 -1 1 590336 ultralytics.nn.modules.conv.Conv [256, 256, 3, 2] 17 [-1, 12] 1 0 ultralytics.nn.modules.conv.Concat [1] 18 -1 3 4592640 ultralytics.nn.modules.block.C2f [768, 512, 3] 19 -1 1 2360320 ultralytics.nn.modules.conv.Conv [512, 512, 3, 2] 20 [-1, 9] 1 0 ultralytics.nn.modules.conv.Concat [1] 21 -1 3 4723712 ultralytics.nn.modules.block.C2f [1024, 512, 3] 22 [15, 18, 21] 1 5583571 ultralytics.nn.modules.head.Detect [1, [256, 512, 512]] Model summary: 365 layers, 43630611 parameters, 43630595 gradients, 165.4 GFLOPs Transferred 589/595 items from pretrained weights TensorBoard: Start with 'tensorboard --logdir runs\detect\train2', view at http://localhost:6006/ Freezing layer 'model.22.dfl.conv.weight' AMP: running Automatic Mixed Precision (AMP) checks with YOLOv8n... Downloading https://github.com/ultralytics/assets/releases/download/v8.1.0/yolov8n.pt to 'yolov8n.pt'...
100%|█████████████████████████████████████████████████████████████████████████████| 6.23M/6.23M [00:01<00:00, 4.02MB/s]
AMP: checks passed ✅
train: Scanning D:\Learrning\great learning\capston Proj\dataset\yolo\labels\train.cache... 5405 images, 545 background val: Scanning D:\Learrning\great learning\capston Proj\dataset\yolo\labels\val.cache... 607 images, 55 backgrounds, 0 c
Plotting labels to runs\detect\train2\labels.jpg... optimizer: 'optimizer=auto' found, ignoring 'lr0=0.01' and 'momentum=0.937' and determining best 'optimizer', 'lr0' and 'momentum' automatically... optimizer: AdamW(lr=0.002, momentum=0.9) with parameter groups 97 weight(decay=0.0), 104 weight(decay=0.0005), 103 bias(decay=0.0) TensorBoard: model graph visualization added ✅ Image sizes 640 train, 640 val Using 8 dataloader workers Logging results to runs\detect\train2 Starting training for 10 epochs... Closing dataloader mosaic Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size
1/10 10.6G 2.27 2.801 2.394 23 640: 100%|██████████| 372/372 [1:38:38<00:00,
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 21/21 [00:18
all 662 962 0.012 0.797 0.0225 0.00639
Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size
2/10 10.2G 2.216 2.466 2.253 19 640: 100%|██████████| 372/372 [1:24:56<00:00,
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 21/21 [00:19
all 662 962 0.238 0.181 0.123 0.038
Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size
3/10 10.3G 2.148 2.382 2.169 24 640: 100%|██████████| 372/372 [1:32:01<00:00,
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 21/21 [00:22
all 662 962 0.0236 0.052 0.00763 0.00175
Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size
4/10 10.2G 2.09 2.245 2.086 21 640: 100%|██████████| 372/372 [1:27:26<00:00,
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 21/21 [00:22
all 662 962 0.372 0.364 0.3 0.106
Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size
5/10 10.2G 2.049 2.149 2.042 24 640: 100%|██████████| 372/372 [1:18:41<00:00,
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 21/21 [00:44
all 662 962 0.401 0.452 0.39 0.144
Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size
6/10 10.3G 2.023 2.077 1.98 18 640: 100%|██████████| 372/372 [1:36:13<00:00,
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 21/21 [00:29
all 662 962 0.442 0.484 0.409 0.154
Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size
7/10 10.2G 1.993 2.036 1.942 20 640: 100%|██████████| 372/372 [1:22:32<00:00,
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 21/21 [00:56
all 662 962 0.39 0.437 0.349 0.128
Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size
8/10 10.2G 1.956 1.98 1.921 20 640: 100%|██████████| 372/372 [1:23:04<00:00,
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 21/21 [00:37
all 662 962 0.493 0.497 0.471 0.185
Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size
9/10 10.2G 1.929 1.945 1.893 24 640: 100%|██████████| 372/372 [1:17:12<00:00,
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 21/21 [00:39
all 662 962 0.498 0.473 0.44 0.162
Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size
10/10 10.2G 1.91 1.892 1.876 22 640: 100%|██████████| 372/372 [1:10:55<00:00,
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 21/21 [01:26
all 662 962 0.486 0.492 0.467 0.187
10 epochs completed in 14.333 hours. Optimizer stripped from runs\detect\train2\weights\last.pt, 87.6MB Optimizer stripped from runs\detect\train2\weights\best.pt, 87.6MB Validating runs\detect\train2\weights\best.pt... Ultralytics YOLOv8.1.30 🚀 Python-3.8.5 torch-2.2.1+cu121 CUDA:0 (NVIDIA GeForce RTX 2060, 6144MiB) Model summary (fused): 268 layers, 43607379 parameters, 0 gradients, 164.8 GFLOPs
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 21/21 [00:22
all 662 962 0.487 0.494 0.468 0.187
Speed: 0.4ms preprocess, 28.6ms inference, 0.0ms loss, 1.5ms postprocess per image
Results saved to runs\detect\train2
def plot_val_pred(demo_patient_id, verbose=True, split='val'):
demo_img_path = DATASET_DIR + f'images/{split}/' + demo_patient_id + '.jpg'
demo_label_path = DATASET_DIR + f'labels/{split}/' + demo_patient_id + '.txt'
res = model(demo_img_path, verbose=verbose)
if verbose:
print(res[0].probs)
print(res[0].boxes.xywh)
plt.imshow(cv2.imread(demo_img_path))
img_size = 1014
if os.path.isfile(demo_label_path):
with open(demo_label_path, "r") as f:
for line in f:
if verbose:
print(line)
class_id, rx, ry, rw, rh = list(map(float, line.strip().split()))
x, y, w, h = revert_bbox(rx, ry, rw, rh)
plt.plot([x, x, x+w, x+w, x], [y, y+h, y+h, y, y], c='blue')
for box in res[0].boxes.xywh.cpu():
px, py, pw, ph = box
plt.plot([px-pw/2, px-pw/2, px+pw/2, px+pw/2, px-pw/2], [py-ph/2, py+ph/2, py+ph/2, py-ph/2, py-ph/2], c='orange')
def random_value(series):
return series.iloc[random.randrange(0, len(series))]
def plot_examples(series, rows = 5, cols = 2, split='val'):
plt.suptitle(split)
plt.figure(figsize=(10*cols,10*rows))
for h in range(rows):
for w in range(cols):
plt.subplot(rows, cols, h*2+w+1)
plot_val_pred(random_value(series), verbose=False, split=split)
plot_examples(train_series, 2, 2, 'train')
<Figure size 432x288 with 0 Axes>
plot_examples(val_series, 2, 2, 'val')
<Figure size 432x288 with 0 Axes>
model.save(filename='yolo8_pnecapstone.pt')
import pickle
modelyolo = torch.load('yolo8_pnecapstone.pt')
# Save the model to a pickle file
with open('yolov8n_pne.pkl', 'wb') as f:
pickle.dump(modelyolo, f,protocol=pickle.HIGHEST_PROTOCOL)
for file in tqdm(os.listdir(TEST_SRC_DIR)):
src_path = TEST_SRC_DIR + file
dcm_data = pydicom.dcmread(src_path)
image_array = dcm_data.pixel_array
image = Image.fromarray(image_array)
image.save(TEST_IMG_DIR + os.path.splitext(file)[0] + '.jpg')
100%|██████████████████████████████████████████████████████████████████████████████| 3000/3000 [02:05<00:00, 23.84it/s]
results_train = results
results = model(TEST_IMG_DIR, verbose=False, conf=0.28) #
WARNING ⚠️ inference results will accumulate in RAM unless `stream=True` is passed, causing potential out-of-memory
errors for large sources or long-running streams and videos. See https://docs.ultralytics.com/modes/predict/ for help.
Example:
results = model(source=..., stream=True) # generator of Results objects
for r in results:
boxes = r.boxes # Boxes object for bbox outputs
masks = r.masks # Masks object for segment masks outputs
probs = r.probs # Class probabilities for classification outputs
def get_id_from_path(path):
return os.path.splitext(os.path.basename(path))[0]
print(get_id_from_path(results[1].path))
print(results[1].boxes.xywh)
print(results[1].boxes.conf)
0005d3cc-3c3f-40b9-93c3-46231c3eb813 tensor([], device='cuda:0', size=(0, 4)) tensor([], device='cuda:0')
with open('submissionyolo8pne.csv', 'w') as file:
file.write("patientId,PredictionString\n")
for result in tqdm(results):
line = get_id_from_path(result.path) + ','
for conf, xywh in zip(result.boxes.conf, result.boxes.xywh):
x, y, w, h = xywh
line += f"{conf:.2f} {x-w/2:.2f} {y-h/2:.2f} {w:.2f} {h:.2f} "
line = line.strip()
file.write(line+"\n")
100%|████████████████████████████████████████████████████████████████████████████| 3000/3000 [00:00<00:00, 4248.84it/s]
from pathlib import Path
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from PIL import Image
path = Path('submissionyolo8pne.csv')
df = pd.read_csv(path)
print(path.name)
df['pred_count'] = df['PredictionString'].apply(lambda x: 0 if pd.isna(x) else int(len(x.split()) / 5))
df['pred_count'].value_counts().sort_index()
submissionyolo8pne.csv
0 2674 1 214 2 108 3 4 Name: pred_count, dtype: int64
def str_to_boxes(s: str) -> list: # return c,x,y,w,h
if pd.isna(s) or len(s) == 0:
return []
boxes = []
n = len(s.split()) // 5
for i in range(n):
box = s.split()[i * 5:i * 5 + 5]
boxes.append(list(map(float, box)))
return boxes
def remove_empty_boxes(s: str) -> str:
if pd.isna(s) or len(s) == 0:
return s
n = len(s.split()) // 5
data = s.split()
for i in range(n):
box = data[i * 5:i * 5 + 5]
if float(box[2]) * float(box[3]) == 0:
s = s.replace(' '.join(map(str, box)), '').strip()
return s
df['PredictionString'] = df['PredictionString'].apply(remove_empty_boxes)
def box_areas_utils(box1, box2): # corner coords
_, left_x1, left_y1, w1, h1 = box1
_, left_x2, left_y2, w2, h2 = box2
assert w1 * h1 * w2 * h2 > 0, 'w or h is 0'
right_x1, right_x2 = left_x1 + w1, left_x2 + w2
top_y1, top_y2 = left_y1 + h1, left_y2 + h2
area1, area2 = w1 * h1, w2 * h2
right_xi = min(right_x1, right_x2)
left_xi = max(left_x1, left_x2)
top_yi = min(top_y1, top_y2)
bottom_yi = max(left_y1, left_y2)
if right_xi <= left_xi or top_yi <= bottom_yi:
intersection = 0
else:
intersection = (right_xi - left_xi) * (top_yi - bottom_yi)
union = area1 + area2 - intersection
return area1, area2, intersection, union
def iou(box1, box2):
area1, area2, intersection, union = box_areas_utils(box1, box2)
return intersection / union
def two_boxes_overlap(box1, box2) -> bool:
return iou(box1, box2) > 0.3
def one_box_inside_another(box1, box2) -> bool:
area1, area2, intersection, union = box_areas_utils(box1, box2)
return intersection / area1 > 0.7 or intersection / area2 > 0.7
def merge_boxes(box1, box2) -> (float, float, float, float, float): # c,x,y,w,h - bottom left corner (0,0)
c1, x1, y1, w1, h1 = box1
c2, x2, y2, w2, h2 = box2
min_x, min_y = min([x1, x2]), min([y1, y2])
max_x, max_y = max([x1 + w1, x2 + w2]), max([y1 + h1, y2 + h2])
w, h = max_x - min_x, max_y - min_y
# reduce w, h by 10%
dw, dh = w * 0.05, h * 0.05
w, h = w * 0.9, h * 0.9
return (c1 + c2) / 2, (x1 + x2) / 2, (y1 + y2) / 2, (w1+w2) / 2, (h1+h2) / 2
def detect_overlapping(s: str, type='both') -> bool:
if pd.isna(s):
return False
n = len(s.split()) // 5
for i in range(n):
box1 = list(map(float, s.split()[i * 5:i * 5 + 5]))
for j in range(n):
if i == j:
continue
box2 = list(map(float, s.split()[j * 5:j * 5 + 5]))
if type == 'both':
if two_boxes_overlap(box1, box2) or one_box_inside_another(box1, box2):
return True
elif type == 'overlap':
if two_boxes_overlap(box1, box2) and not one_box_inside_another(box1, box2):
return True
elif type == 'inside':
if one_box_inside_another(box1, box2):
return True
return False
def merge_overlapping(s: str) -> str:
if pd.isna(s):
return s
boxes = str_to_boxes(s)
for i in range(len(boxes)):
for j in range(i + 1, len(boxes)):
if boxes[i] is None or boxes[j] is None:
continue
if two_boxes_overlap(boxes[i], boxes[j]) or \
one_box_inside_another(boxes[i], boxes[j]):
boxes[i] = merge_boxes(boxes[i], boxes[j])
boxes[j] = None
return ' '.join([' '.join(map(str, c)) for c in boxes if c is not None]).strip()
df['overlaps'] = df['PredictionString'].apply(lambda s: detect_overlapping(s, type='overlap'));
df['inside_box'] = df['PredictionString'].apply(lambda s: detect_overlapping(s, type='inside'));
print(df.query('pred_count>0')['overlaps'].value_counts())
print(df.query('pred_count>0')['inside_box'].value_counts())
False 326 Name: overlaps, dtype: int64 False 321 True 5 Name: inside_box, dtype: int64
df[df['overlaps']]['pred_count'].value_counts().sort_index()
Series([], Name: pred_count, dtype: int64)
df['PredictionString_'] = df['PredictionString']
s = df.query('inside_box').sample(1).iloc[0]
img = Image.open(f'test_images_yolo/{s["patientId"]}.jpg')
img = img.convert('RGB')
ax = plt.gca()
boxes = str_to_boxes(s['PredictionString_'])
for b in boxes:
rect = patches.Rectangle((b[1], b[2]), b[3], b[4], linewidth=1, edgecolor='r', facecolor='none')
ax.add_patch(rect)
fixed_s = merge_overlapping(s['PredictionString_'])
boxes_fixed = str_to_boxes(fixed_s)
for b in boxes_fixed:
rect = patches.Rectangle((b[1], b[2]), b[3], b[4], linewidth=1, edgecolor='b', facecolor='none', linestyle=':')
ax.add_patch(rect)
plt.imshow(img);
df['PredictionString'] = df['PredictionString'].apply(merge_overlapping)
df[['patientId', 'PredictionString']].to_csv(path.name, index=False)
result_val = model.val()
Ultralytics YOLOv8.1.30 🚀 Python-3.8.5 torch-2.2.1+cu121 CUDA:0 (NVIDIA GeForce RTX 2060, 6144MiB)
val: Scanning D:\Learrning\great learning\capston Proj\dataset\yolo\labels\val.cache... 607 images, 55 backgrounds, 0 c
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 42/42 [04:20
all 662 962 0.489 0.495 0.468 0.187
Speed: 0.6ms preprocess, 387.2ms inference, 0.0ms loss, 1.3ms postprocess per image
Results saved to runs\detect\train23
result_val.results_dict
{'metrics/precision(B)': 0.48852707193435346,
'metrics/recall(B)': 0.49480249480249483,
'metrics/mAP50(B)': 0.46836995131312675,
'metrics/mAP50-95(B)': 0.1869621628931632,
'fitness': 0.21510294173515956}